diff options
author | Michael P | 2011-08-05 02:07:38 +0000 |
---|---|---|
committer | Michael P | 2011-08-05 02:07:38 +0000 |
commit | 8a15033d7d7ae7cbe9a100ea88b8e18f033f0cb4 (patch) | |
tree | 0afa598503e7af6615149db94f0de8509bb3e7dc | |
parent | 87502bc809b852337e09f391317cbbc0cc35faf8 (diff) |
Support for temporary TABLE/VIEW
Temporary tables and views are supported so as it uses the same
interface as PostgreSQL.
For Postgres-XC, it is possible for users to create un the cluster
temporary tables that are replicated or distributed the same way
as permanent tables.
As those objects are session-limited, creation is made automatically on
the Datanodes at the moment of query launch like normal DDL.
Views are created only on local Coordinators.
Support for ON COMMIT DROP/PRESERVE ROWS/DELETE ROWS is guarranted the
same way as PostgreSQL.
Support for INDEX, DROP, RENAME is also guarranted like normal PostgreSQL.
One of the main changes is the addition of a DISCARD ALL clean up command
run in pooler for pooler connections used during session to Datanodes when
session finishes. This command is run the same way as RESET ALL for SET commands
at the end of a session.
A new regression test case called xc_temp has been added to check JOINs between
temporary and persistent tables for the types types of distribution supported by
Postgres-XC: REPLICATION, HASH (equivalent to MODULO), ROUND ROBIN.
35 files changed, 2549 insertions, 768 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 1a199789b1..e3e0e0f9aa 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -1962,6 +1962,14 @@ CommitTransaction(bool contact_gtm) char implicitgid[256]; TransactionId xid = InvalidTransactionId; + /* + * Check if there are any On Commit actions and force temporary object flag. + * This is possible in the case of a session using ON COMMIT DELETE ROWS. + * It is essential to do this check *before* calling PGXCNodeIsImplicit2PC. + */ + if (IsOnCommitActions()) + ExecSetTempObjectIncluded(); + if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && contact_gtm) PreparePGXCNodes = PGXCNodeIsImplicit2PC(&PrepareLocalCoord); @@ -2330,6 +2338,15 @@ PrepareTransaction(void) ShowTransactionState("PrepareTransaction"); +#ifdef PGXC + /* + * Check if there are any On Commit actions and force temporary object flag. + * This is possible in the case of a session using ON COMMIT DELETE ROWS. + */ + if (IsOnCommitActions()) + ExecSetTempObjectIncluded(); +#endif + /* * check the current transaction state */ diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index d09bef0682..f18a132219 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -4,7 +4,8 @@ * * PostgreSQL object comments utility code. * - * Copyright (c) 1996-2011, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * * IDENTIFICATION * src/backend/commands/comment.c @@ -460,3 +461,42 @@ GetComment(Oid oid, Oid classoid, int32 subid) return comment; } + + +#ifdef PGXC +/* + * GetCommentObjectId + * + * Return Object ID of object commented + * Note: This function uses portions of the code of CommentObject, + * even if this code is duplicated this is done like this to facilitate + * merges with PostgreSQL head. + */ +Oid +GetCommentObjectId(CommentStmt *stmt) +{ + ObjectAddress address; + Relation relation; + + if (stmt->objtype == OBJECT_DATABASE && list_length(stmt->objname) == 1) + { + char *database = strVal(linitial(stmt->objname)); + + if (!OidIsValid(get_database_oid(database, true))) + { + ereport(WARNING, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%s\" does not exist", database))); + return InvalidOid; + } + } + + address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs, + &relation, ShareUpdateExclusiveLock); + + if (relation != NULL) + relation_close(relation, NoLock); + + return address.objectId; +} +#endif diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 952b88b533..bfaf6e2860 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -918,6 +918,12 @@ DoCopy(const CopyStmt *stmt, const char *queryString) rte->relkind = rel->rd_rel->relkind; rte->requiredPerms = required_access; +#ifdef PGXC + /* In case COPY is used on a temporary table, never use 2PC for implicit commits */ + if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) + ExecSetTempObjectIncluded(); +#endif + tupDesc = RelationGetDescr(rel); attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist); foreach(cur, attnums) diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 831886f46d..851b0dca3b 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -132,7 +132,8 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString) * Add a RemoteQuery node for a query at top level on a remote Coordinator */ if (is_top_level) - parsetree_list = AddRemoteQueryNode(parsetree_list, queryString, EXEC_ON_ALL_NODES); + parsetree_list = AddRemoteQueryNode(parsetree_list, queryString, + EXEC_ON_ALL_NODES, false); #endif /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 644e572934..7fe0015868 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -89,6 +89,7 @@ #include "pgxc/pgxc.h" #include "access/gtm.h" #include "commands/sequence.h" +#include "pgxc/execRemote.h" #endif /* @@ -439,20 +440,11 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) * code. This is needed because calling code might not expect untrusted * tables to appear in pg_temp at the front of its search path. */ -#ifdef PGXC - if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP && - IsUnderPostmaster && - relkind != RELKIND_SEQUENCE) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("PG-XC does not yet support temporary tables"))); -#else if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP && InSecurityRestrictedOperation()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("cannot create temporary table within security-restricted operation"))); -#endif /* * Look up the namespace in which we are supposed to create the relation, @@ -9462,3 +9454,110 @@ AtEOSubXact_on_commit_actions(bool isCommit, SubTransactionId mySubid, } } } + +#ifdef PGXC +/* + * IsTempTable + * + * Check if given table Oid is temporary. + */ +bool +IsTempTable(Oid relid) +{ + Relation rel; + bool res; + /* + * PGXCTODO: Is it correct to open without locks? + * we just check if this table is temporary though... + */ + rel = relation_open(relid, NoLock); + res = rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP; + relation_close(rel, NoLock); + return res; +} + +/* + * IsIndexUsingTemp + * + * Check if given index relation uses temporary tables. + */ +bool +IsIndexUsingTempTable(Oid relid) +{ + bool res = false; + HeapTuple tuple; + Oid parent_id = InvalidOid; + + tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(relid)); + if (HeapTupleIsValid(tuple)) + { + Form_pg_index index = (Form_pg_index) GETSTRUCT(tuple); + parent_id = index->indrelid; + + /* Release system cache BEFORE looking at the parent table */ + ReleaseSysCache(tuple); + + res = IsTempTable(parent_id); + } + else + res = false; /* Default case */ + + return res; +} + +/* + * IsOnCommitDeleteRows + * + * Check if there are any on-commit actions activated + * This is possible in the case of ON COMMIT DELETE ROWS for example. + * In this case 2PC cannot be used. + */ +bool +IsOnCommitActions(void) +{ + return list_length(on_commits) > 0; +} + +/* + * DropTableThrowErrorExternal + * + * Error interface for DROP when looking for execution node type. + */ +void +DropTableThrowErrorExternal(RangeVar *relation, ObjectType removeType, bool missing_ok) +{ + char relkind; + + /* Determine required relkind */ + switch (removeType) + { + case OBJECT_TABLE: + relkind = RELKIND_RELATION; + break; + + case OBJECT_INDEX: + relkind = RELKIND_INDEX; + break; + + case OBJECT_SEQUENCE: + relkind = RELKIND_SEQUENCE; + break; + + case OBJECT_VIEW: + relkind = RELKIND_VIEW; + break; + + case OBJECT_FOREIGN_TABLE: + relkind = RELKIND_FOREIGN_TABLE; + break; + + default: + elog(ERROR, "unrecognized drop object type: %d", + (int) removeType); + relkind = 0; /* keep compiler quiet */ + break; + } + + DropErrorMsgNonExistent(relation->relname, relkind, missing_ok); +} +#endif diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index d3b5c7793b..bc32049b87 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -47,6 +47,7 @@ #include "catalog/pg_type.h" #include "executor/executor.h" #include "rewrite/rewriteManip.h" +#include "commands/tablecmds.h" #endif #include "utils/lsyscache.h" @@ -2601,8 +2602,15 @@ create_remotequery_plan(PlannerInfo *root, Path *best_path, /* * XXX: should use GENERIC OPTIONS like 'foreign_relname' or something for * the foreign table name instead of the local name ? + * + * A temporary table does not use namespace as it may not be + * consistent among nodes cluster. Relation name is sufficient. */ - appendStringInfo(&sql, "%s.%s %s", nspname_q, relname_q, aliasname_q); + if (IsTempTable(rte->relid)) + appendStringInfo(&sql, "%s %s", relname_q, aliasname_q); + else + appendStringInfo(&sql, "%s.%s %s", nspname_q, relname_q, aliasname_q); + pfree(nspname); pfree(relname); if (nspname_q != nspname_q) diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index 7da7f848af..e3499134db 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -46,6 +46,7 @@ #include "utils/syscache.h" #include "utils/numeric.h" #include "access/hash.h" +#include "commands/tablecmds.h" #include "utils/timestamp.h" #include "utils/date.h" @@ -171,7 +172,8 @@ static int handle_limit_offset(RemoteQuery *query_step, Query *query, PlannedStm static void InitXCWalkerContext(XCWalkerContext *context); static RemoteQuery *makeRemoteQuery(void); static void validate_part_col_updatable(const Query *query); - +static bool contains_temp_tables(List *rtable); +static bool contains_only_pg_catalog(List *rtable); /* * Find position of specified substring in the string @@ -1403,7 +1405,7 @@ examine_conditions_fromlist(Node *treenode, XCWalkerContext *context) * only contain pg_catalog entries. */ static bool -contains_only_pg_catalog (List *rtable) +contains_only_pg_catalog(List *rtable) { ListCell *item; @@ -1416,13 +1418,39 @@ contains_only_pg_catalog (List *rtable) { if (get_rel_namespace(rte->relid) != PG_CATALOG_NAMESPACE) return false; - } else if (rte->rtekind == RTE_SUBQUERY && - !contains_only_pg_catalog (rte->subquery->rtable)) + } + else if (rte->rtekind == RTE_SUBQUERY && + !contains_only_pg_catalog(rte->subquery->rtable)) return false; } return true; } +/* + * Returns true if at least one temporary table is in use + * in query (and its subqueries) + */ +static bool +contains_temp_tables(List *rtable) +{ + ListCell *item; + + foreach(item, rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(item); + + if (rte->rtekind == RTE_RELATION) + { + if (IsTempTable(rte->relid)) + return true; + } + else if (rte->rtekind == RTE_SUBQUERY && + contains_temp_tables(rte->subquery->rtable)) + return true; + } + + return false; +} /* * get_plan_nodes - determine the nodes to execute the command on. @@ -1934,6 +1962,7 @@ makeRemoteQuery(void) result->paramval_data = NULL; result->paramval_len = 0; result->exec_direct_type = EXEC_DIRECT_NONE; + result->is_temp = false; result->relname = NULL; result->remotejoin = false; @@ -2737,12 +2766,16 @@ pgxc_planner(Query *query, int cursorOptions, ParamListInfo boundParams) if (query->commandType != CMD_SELECT) result->resultRelations = list_make1_int(query->resultRelation); - if (contains_only_pg_catalog (query->rtable)) + if (contains_only_pg_catalog(query->rtable)) { result = standard_planner(query, cursorOptions, boundParams); return result; } + /* Check if temporary tables are in use in target list */ + if (contains_temp_tables(query->rtable)) + query_step->is_temp = true; + if (query_step->exec_nodes == NULL) get_plan_nodes_command(query_step, root); @@ -3184,7 +3217,7 @@ GetHashExecNodes(RelationLocInfo *rel_loc_info, ExecNodes **exec_nodes, const Ex * duplicated queries on Datanodes. */ List * -AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType remoteExecType) +AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType remoteExecType, bool is_temp) { List *result = stmts; @@ -3199,6 +3232,7 @@ AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType rem step->combine_type = COMBINE_TYPE_SAME; step->sql_statement = queryString; step->exec_type = remoteExecType; + step->is_temp = is_temp; result = lappend(result, step); } diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index 1efb364333..121245d696 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -52,6 +52,7 @@ static bool autocommit = true; static bool is_ddl = false; static bool implicit_force_autocommit = false; +static bool temp_object_included = false; static PGXCNodeHandle **write_node_list = NULL; static int write_node_count = 0; static char *begin_string = NULL; @@ -1536,11 +1537,27 @@ finish: if (res != 0) { - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("Could not prepare transaction on data nodes"))); + + /* In case transaction has operated on temporary objects */ + if (temp_object_included) + { + /* Reset temporary object flag */ + temp_object_included = false; + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("cannot PREPARE a transaction that has operated on temporary tables"))); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("Could not prepare transaction on data nodes"))); + } } + /* Reset temporary object flag */ + temp_object_included = false; + return local_operation; } @@ -1824,6 +1841,9 @@ finish: is_ddl = false; clear_write_node_list(); + /* Reset temporary object flag */ + temp_object_included = false; + /* Clean up connections */ pfree_pgxc_all_handles(pgxc_connections); @@ -1973,6 +1993,9 @@ finish: is_ddl = false; clear_write_node_list(); + /* Reset temporary object flag */ + temp_object_included = false; + /* Free node list taken from GTM */ if (datanodes && datanodecnt != 0) free(datanodes); @@ -2113,6 +2136,9 @@ finish: is_ddl = false; clear_write_node_list(); + /* Reset temporary object flag */ + temp_object_included = false; + /* Free node list taken from GTM */ if (datanodes) free(datanodes); @@ -2210,6 +2236,9 @@ finish: is_ddl = false; clear_write_node_list(); + /* Reset temporary object flag */ + temp_object_included = false; + /* Clean up connections */ pfree_pgxc_all_handles(pgxc_connections); if (res != 0) @@ -2284,6 +2313,9 @@ finish: is_ddl = false; clear_write_node_list(); + /* Reset temporary object flag */ + temp_object_included = false; + /* Clean up connections */ pfree_pgxc_all_handles(pgxc_connections); return res; @@ -3217,6 +3249,10 @@ do_query(RemoteQueryState *node) bool need_tran; PGXCNodeAllHandles *pgxc_connections; + /* Be sure to set temporary object flag if necessary */ + if (step->is_temp) + temp_object_included = true; + /* * Get connections for Datanodes only, utilities and DDLs * are launched in ExecRemoteUtility @@ -4033,6 +4069,9 @@ ExecRemoteUtility(RemoteQuery *node) implicit_force_autocommit = force_autocommit; + /* A transaction using temporary objects cannot use 2PC */ + temp_object_included = node->is_temp; + remotestate = CreateResponseCombiner(0, node->combine_type); pgxc_connections = get_exec_connections(NULL, node->exec_nodes, exec_type); @@ -4516,12 +4555,14 @@ PGXCNodeIsImplicit2PC(bool *prepare_local_coord) /* * In case of an autocommit or forced autocommit transaction, 2PC is not involved - * This case happens for Utilities using force autocommit (CREATE DATABASE, VACUUM...) + * This case happens for Utilities using force autocommit (CREATE DATABASE, VACUUM...). + * For a transaction using temporary objects, 2PC is not authorized. */ - if (implicit_force_autocommit) + if (implicit_force_autocommit || temp_object_included) { *prepare_local_coord = false; implicit_force_autocommit = false; + temp_object_included = false; return false; } @@ -4622,3 +4663,15 @@ int DataNodeCopyInBinaryForAll(char *msg_buf, int len, PGXCNodeHandle** copy_con return 0; } + +/* + * ExecSetTempObjectIncluded + * + * Set Temp object flag on the fly for transactions + * This flag will be reinitialized at commit. + */ +void +ExecSetTempObjectIncluded(void) +{ + temp_object_included = true; +} diff --git a/src/backend/pgxc/pool/poolmgr.c b/src/backend/pgxc/pool/poolmgr.c index 463bd5a170..c0d8d56aab 100644 --- a/src/backend/pgxc/pool/poolmgr.c +++ b/src/backend/pgxc/pool/poolmgr.c @@ -93,7 +93,13 @@ static void agent_init(PoolAgent *agent, const char *database, const char *user_ static void agent_destroy(PoolAgent *agent); static void agent_create(void); static void agent_handle_input(PoolAgent *agent, StringInfo s); -static int agent_set_command(PoolAgent *agent, const char *set_command, bool is_local); +static int agent_session_command(PoolAgent *agent, + const char *set_command, + PoolCommandType command_type); +static int agent_set_command(PoolAgent *agent, + const char *set_command, + PoolCommandType command_type); +static int agent_temp_command(PoolAgent *agent); static DatabasePool *create_database_pool(const char *database, const char *user_name); static void insert_database_pool(DatabasePool *pool); static int destroy_database_pool(const char *database, const char *user_name); @@ -107,7 +113,7 @@ static int *agent_acquire_connections(PoolAgent *agent, List *datanodelist, List static int cancel_query_on_connections(PoolAgent *agent, List *datanodelist, List *coordlist); static PGXCNodePoolSlot *acquire_connection(DatabasePool *dbPool, int node, char client_conn_type); static void agent_release_connections(PoolAgent *agent, List *dn_discard, List *co_discard); -static void agent_reset_params(PoolAgent *agent, List *dn_list, List *co_list); +static void agent_reset_session(PoolAgent *agent, List *dn_list, List *co_list); static void release_connection(DatabasePool *dbPool, PGXCNodePoolSlot *slot, int index, bool clean, char client_conn_type); static void destroy_slot(PGXCNodePoolSlot *slot); @@ -490,6 +496,7 @@ agent_create(void) agent->coord_connections = NULL; agent->session_params = NULL; agent->local_params = NULL; + agent->is_temp = false; agent->pid = 0; /* Append new agent to the list */ @@ -543,30 +550,44 @@ PoolManagerConnect(PoolHandle *handle, const char *database, const char *user_na } int -PoolManagerSetCommand(bool is_local, const char *set_command) +PoolManagerSetCommand(PoolCommandType command_type, const char *set_command) { int n32; char msgtype = 's'; - Assert(set_command); Assert(Handle); /* Message type */ pool_putbytes(&Handle->port, &msgtype, 1); /* Message length */ - n32 = htonl(strlen(set_command) + 10); + if (set_command) + n32 = htonl(strlen(set_command) + 13); + else + n32 = htonl(12); + pool_putbytes(&Handle->port, (char *) &n32, 4); /* LOCAL or SESSION parameter ? */ - pool_putbytes(&Handle->port, (char *) &is_local, 1); - - /* Length of SET command string */ - n32 = htonl(strlen(set_command) + 1); + n32 = htonl(command_type); pool_putbytes(&Handle->port, (char *) &n32, 4); - /* Send command string followed by \0 terminator */ - pool_putbytes(&Handle->port, set_command, strlen(set_command) + 1); + if (set_command) + { + /* Length of SET command string */ + n32 = htonl(strlen(set_command) + 1); + pool_putbytes(&Handle->port, (char *) &n32, 4); + + /* Send command string followed by \0 terminator */ + pool_putbytes(&Handle->port, set_command, strlen(set_command) + 1); + } + else + { + /* Send empty command */ + n32 = htonl(0); + pool_putbytes(&Handle->port, (char *) &n32, 4); + } + pool_flush(&Handle->port); /* Get result */ @@ -628,10 +649,10 @@ agent_destroy(PoolAgent *agent) co_conn = lappend_int(co_conn, i+1); /* - * agent is being destroyed, so reset session parameters - * before putting back connections to pool + * Agent is being destroyed, so reset session parameters + * and temporary objects before putting back connections to pool. */ - agent_reset_params(agent, dn_conn, co_conn); + agent_reset_session(agent, dn_conn, co_conn); /* release them all */ agent_release_connections(agent, dn_conn, co_conn); @@ -881,8 +902,8 @@ agent_handle_input(PoolAgent * agent, StringInfo s) { const char *database = NULL; const char *user_name = NULL; - const char *set_command; - bool is_local; + const char *set_command = NULL; + PoolCommandType command_type; int datanodecount; int coordcount; List *datanodelist = NIL; @@ -1043,16 +1064,19 @@ agent_handle_input(PoolAgent * agent, StringInfo s) list_free(datanodelist); list_free(coordlist); break; - case 's': /* SET COMMAND */ + case 's': /* Session-related COMMAND */ pool_getmessage(&agent->port, s, 0); /* Determine if command is local or session */ - is_local = (bool) pq_getmsgbyte(s); - /* Get the SET command */ + command_type = (PoolCommandType) pq_getmsgint(s, 4); + /* Get the SET command if necessary */ len = pq_getmsgint(s, 4); - set_command = pq_getmsgbytes(s, len); + if (len != 0) + set_command = pq_getmsgbytes(s, len); + pq_getmsgend(s); - res = agent_set_command(agent, set_command, is_local); + /* Manage command depending on its type */ + res = agent_session_command(agent, set_command, command_type); /* Send success result */ pool_sendres(&agent->port, res); @@ -1068,11 +1092,46 @@ agent_handle_input(PoolAgent * agent, StringInfo s) } /* + * Manage a session command for pooler + */ +static int +agent_session_command(PoolAgent *agent, const char *set_command, PoolCommandType command_type) +{ + int res; + + switch (command_type) + { + case POOL_CMD_LOCAL_SET: + case POOL_CMD_GLOBAL_SET: + res = agent_set_command(agent, set_command, command_type); + break; + case POOL_CMD_TEMP: + res = agent_temp_command(agent); + break; + default: + res = -1; + break; + } + + return res; +} + +/* + * Set agent flag that a temporary object is in use. + */ +static int +agent_temp_command(PoolAgent *agent) +{ + agent->is_temp = true; + return 0; +} + +/* * Save a SET command and distribute it to the agent connections * already in use. */ static int -agent_set_command(PoolAgent *agent, const char *set_command, bool is_local) +agent_set_command(PoolAgent *agent, const char *set_command, PoolCommandType command_type) { char *params_string; int i; @@ -1080,11 +1139,16 @@ agent_set_command(PoolAgent *agent, const char *set_command, bool is_local) Assert(agent); Assert(set_command); + Assert(command_type == POOL_CMD_LOCAL_SET || command_type == POOL_CMD_GLOBAL_SET); - if (is_local) + if (command_type == POOL_CMD_LOCAL_SET) params_string = agent->local_params; - else + else if (command_type == POOL_CMD_GLOBAL_SET) params_string = agent->session_params; + else + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("Set command process failed"))); /* First command recorded */ if (!params_string) @@ -1131,9 +1195,9 @@ agent_set_command(PoolAgent *agent, const char *set_command, bool is_local) } /* Save the latest string */ - if (is_local) + if (command_type == POOL_CMD_LOCAL_SET) agent->local_params = params_string; - else + else if (command_type == POOL_CMD_GLOBAL_SET) agent->session_params = params_string; return res; @@ -1278,7 +1342,6 @@ agent_acquire_connections(PoolAgent *agent, List *datanodelist, List *coordlist) static int cancel_query_on_connections(PoolAgent *agent, List *datanodelist, List *coordlist) { - int i; ListCell *nodelist_item; char errbuf[256]; int nCount; @@ -1435,8 +1498,9 @@ agent_release_connections(PoolAgent *agent, List *dn_discard, List *co_discard) return; /* - * If there are some session parameters, do not put back connections to pool - * disconnection will be made when session is cut for this user. + * If there are some session parameters or temporary objects, + * do not put back connections to pool. + * Disconnection will be made when session is cut for this user. * Local parameters are reset when transaction block is finished, * so don't do anything for them, but just reset their list. */ @@ -1445,7 +1509,8 @@ agent_release_connections(PoolAgent *agent, List *dn_discard, List *co_discard) pfree(agent->local_params); agent->local_params = NULL; } - if (agent->session_params) + if (agent->session_params || + agent->is_temp) return; /* Discard first for Datanodes */ @@ -1515,50 +1580,61 @@ agent_release_connections(PoolAgent *agent, List *dn_discard, List *co_discard) * modified by session parameters. */ static void -agent_reset_params(PoolAgent *agent, List *dn_list, List *co_list) +agent_reset_session(PoolAgent *agent, List *dn_list, List *co_list) { - PGXCNodePoolSlot *slot; if (!agent->dn_connections && !agent->coord_connections) return; - /* Parameters are reset, so free commands */ - if (agent->session_params) - { - pfree(agent->session_params); - agent->session_params = NULL; - } - if (agent->local_params) - { - pfree(agent->local_params); - agent->local_params = NULL; - } + if (!agent->session_params && !agent->local_params && !agent->is_temp) + return; - /* Reset Datanode connection params */ - if (dn_list) + /* + * Reset Datanode connection params. + * Discard is only done for Datanodes as Temporary objects are never created + * to other Coordinators in a session. + */ + if (dn_list && + (agent->session_params || agent->local_params || agent->is_temp)) { ListCell *lc; foreach(lc, dn_list) { + PGXCNodePoolSlot *slot; int node = lfirst_int(lc); + Assert(node > 0 && node <= NumDataNodes); slot = agent->dn_connections[node - 1]; /* Reset connection params */ if (slot) - PGXCNodeSendSetQuery(slot->conn, "RESET ALL;"); + { + if (agent->session_params || agent->local_params) + PGXCNodeSendSetQuery(slot->conn, "RESET ALL;"); + + /* + * Discard queries cannot be sent as multiple-queries, + * so do it separately. It is OK to use this slow process + * as session is ending. + */ + if (agent->is_temp) + PGXCNodeSendSetQuery(slot->conn, "DISCARD ALL;"); + } } } /* Reset Coordinator connection params */ - if (co_list) + if (co_list && + (agent->session_params || agent->local_params)) { ListCell *lc; foreach(lc, co_list) { + PGXCNodePoolSlot *slot; int node = lfirst_int(lc); + Assert(node > 0 && node <= NumCoords); slot = agent->coord_connections[node - 1]; @@ -1567,6 +1643,19 @@ agent_reset_params(PoolAgent *agent, List *dn_list, List *co_list) PGXCNodeSendSetQuery(slot->conn, "RESET ALL;"); } } + + /* Parameters are reset, so free commands */ + if (agent->session_params) + { + pfree(agent->session_params); + agent->session_params = NULL; + } + if (agent->local_params) + { + pfree(agent->local_params); + agent->local_params = NULL; + } + agent->is_temp = false; } /* @@ -2070,6 +2159,9 @@ grow_pool(DatabasePool * dbPool, int index, char client_conn_type) errmsg("out of memory"))); } + /* If connection fails, be sure that slot is destroyed cleanly */ + slot->xc_cancelConn = NULL; + /* Establish connection */ slot->conn = PGXCNodeConnect(nodePool->connstr); if (!PGXCNodeConnected(slot->conn)) diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index e4e6ed55b4..9e88b268b2 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -7,6 +7,7 @@ * * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * * * IDENTIFICATION @@ -68,12 +69,15 @@ #include "pgxc/planner.h" #include "pgxc/poolutils.h" #include "pgxc/poolmgr.h" +#include "utils/lsyscache.h" static void ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, - bool force_autocommit, RemoteQueryExecType exec_type); -static RemoteQueryExecType ExecUtilityFindNodes(const char *queryString, - ObjectType objectType, - Oid relid); + bool force_autocommit, RemoteQueryExecType exec_type, + bool is_temp); +static RemoteQueryExecType ExecUtilityFindNodes(ObjectType objectType, + Oid relid, + bool *is_temp); +static RemoteQueryExecType ExecUtilityFindNodesRelkind(Oid relid, bool *is_temp); #endif @@ -653,17 +657,77 @@ standard_ProcessUtility(Node *parsetree, List *stmts; ListCell *l; Oid relOid; +#ifdef PGXC + bool is_temp = false; +#endif /* Run parse analysis ... */ stmts = transformCreateStmt((CreateStmt *) parsetree, queryString); - #ifdef PGXC + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + { + /* + * Scan the list of objects. + * Temporary tables are created on Datanodes only. + * Non-temporary objects are created on all nodes. + * In case temporary and non-temporary objects are mized return an error. + */ + bool is_first = true; + + foreach(l, stmts) + { + Node *stmt = (Node *) lfirst(l); + + if (IsA(stmt, CreateStmt)) + { + CreateStmt *stmt_loc = (CreateStmt *) stmt; + bool is_object_temp = stmt_loc->relation->relpersistence == RELPERSISTENCE_TEMP; + + if (is_first) + { + is_first = false; + if (is_object_temp) + is_temp = true; + } + else + { + if (is_object_temp != is_temp) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE not supported for TEMP and non-TEMP objects"), + errdetail("You should separate TEMP and non-TEMP objects"))); + } + } + else if (IsA(stmt, CreateForeignTableStmt)) + { + /* There are no temporary foreign tables */ + if (is_first) + { + is_first = false; + } + else + { + if (!is_temp) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE not supported for TEMP and non-TEMP objects"), + errdetail("You should separate TEMP and non-TEMP objects"))); + } + } + } + } + /* * Add a RemoteQuery node for a query at top level on a remote Coordinator */ if (isTopLevel) - stmts = AddRemoteQueryNode(stmts, queryString, EXEC_ON_ALL_NODES); + { + if (is_temp) + stmts = AddRemoteQueryNode(stmts, queryString, EXEC_ON_DATANODES, is_temp); + else + stmts = AddRemoteQueryNode(stmts, queryString, EXEC_ON_ALL_NODES, is_temp); + } #endif /* ... and do it */ @@ -676,6 +740,12 @@ standard_ProcessUtility(Node *parsetree, Datum toast_options; static char *validnsps[] = HEAP_RELOPT_NAMESPACES; +#ifdef PGXC + /* Set temporary object object flag in pooler */ + if (is_temp) + PoolManagerSetCommand(POOL_CMD_TEMP, NULL); +#endif + /* Create the table itself */ relOid = DefineRelation((CreateStmt *) stmt, RELKIND_RELATION, @@ -798,6 +868,7 @@ standard_ProcessUtility(Node *parsetree, DropStmt *stmt = (DropStmt *) parsetree; #ifdef PGXC bool is_temp = false; + RemoteQueryExecType exec_type = EXEC_ON_ALL_NODES; /* * We need to check details of the objects being dropped and @@ -806,41 +877,75 @@ standard_ProcessUtility(Node *parsetree, */ if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) { - /* - * Check the list of sequences/tables going to be dropped. - * XC does not allow yet to mix drop of temporary and - * non-temporary objects because this involves to rewrite - * query to process for tables and stop remote query process - * for sequences. - * PGXCTODO: For the time being this is just checked for - * sequences but should also be done for tables - */ - - if (stmt->removeType == OBJECT_SEQUENCE) + switch (stmt->removeType) { - ListCell *cell; - bool is_first = true; - - foreach(cell, stmt->objects) - { - RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell)); - Oid relid; - - relid = RangeVarGetRelid(rel, false); - if (is_first) + case OBJECT_TABLE: + case OBJECT_SEQUENCE: + case OBJECT_VIEW: + case OBJECT_INDEX: { - is_temp = IsTempSequence(relid); - is_first = false; - } - else - { - if (IsTempSequence(relid) != is_temp) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("DROP SEQUENCE not supported for TEMP and non-TEMP sequences"), - errdetail("DROP can be done if TEMP and non-TEMP objects are separated"))); + /* + * Check the list of objects going to be dropped. + * XC does not allow yet to mix drop of temporary and + * non-temporary objects because this involves to rewrite + * query to process for tables. + */ + ListCell *cell; + bool is_first = true; + + foreach(cell, stmt->objects) + { + RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell)); + Oid relid; + + /* + * Do not print result at all, error is thrown + * after if necessary + */ + relid = RangeVarGetRelid(rel, true); + + /* + * In case this relation ID is incorrect throw + * a correct DROP error. + */ + if (!OidIsValid(relid) && !stmt->missing_ok) + DropTableThrowErrorExternal(rel, + stmt->removeType, + stmt->missing_ok); + + /* In case of DROP ... IF EXISTS bypass */ + if (!OidIsValid(relid) && stmt->missing_ok) + continue; + + if (is_first) + { + exec_type = ExecUtilityFindNodes(stmt->removeType, + relid, + &is_temp); + is_first = false; + } + else + { + RemoteQueryExecType exec_type_loc; + bool is_temp_loc; + exec_type_loc = ExecUtilityFindNodes(stmt->removeType, + relid, + &is_temp_loc); + if (exec_type_loc != exec_type || + is_temp_loc != is_temp) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("DROP not supported for TEMP and non-TEMP objects"), + errdetail("You should separate TEMP and non-TEMP objects"))); + } + } } - } + break; + + default: + is_temp = false; + exec_type = EXEC_ON_ALL_NODES; + break; } } #endif @@ -898,20 +1003,9 @@ standard_ProcessUtility(Node *parsetree, } #ifdef PGXC - /* - * Drop can be done on non-temporary objects and temporary objects - * if they are not mixed up. - * PGXCTODO: This should be extended to tables - */ - if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !is_temp) - { - /* Sequence and views exists only on Coordinators */ - if (stmt->removeType == OBJECT_SEQUENCE || - stmt->removeType == OBJECT_VIEW) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS); - else - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); - } + /* DROP is done depending on the object type and its temporary type */ + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + ExecUtilityStmtOnNodes(queryString, NULL, false, exec_type, is_temp); #endif } break; @@ -920,12 +1014,31 @@ standard_ProcessUtility(Node *parsetree, ExecuteTruncate((TruncateStmt *) parsetree); #ifdef PGXC /* - * PGXCTODO - * We may need to check details of the object being truncated and - * run command on correct nodes + * Check details of the object being truncated. + * If at least one temporary table is truncated truncate cannot use 2PC + * at commit. */ - if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + { + bool is_temp = false; + ListCell *cell; + TruncateStmt *stmt = (TruncateStmt *) parsetree; + + foreach(cell, stmt->relations) + { + Oid relid; + RangeVar *rel = (RangeVar *) lfirst(cell); + + relid = RangeVarGetRelid(rel, true); + if (IsTempTable(relid)) + { + is_temp = true; + break; + } + } + + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_DATANODES, is_temp); + } #endif break; @@ -933,13 +1046,23 @@ standard_ProcessUtility(Node *parsetree, CommentObject((CommentStmt *) parsetree); #ifdef PGXC - /* - * PGXCTODO - * Comments on temporary objects need special handling - * depending on their types. - */ + /* Comment objects depending on their object and temporary types */ if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS); + { + bool is_temp = false; + RemoteQueryExecType exec_type = EXEC_ON_ALL_NODES; + CommentStmt *stmt = (CommentStmt *) parsetree; + Oid relid = GetCommentObjectId(stmt); + + /* Commented object may not have a valid object ID, so move to default */ + if (OidIsValid(relid)) + { + exec_type = ExecUtilityFindNodes(stmt->objtype, + relid, + &is_temp); + } + ExecUtilityStmtOnNodes(queryString, NULL, false, exec_type, is_temp); + } #endif break; @@ -981,19 +1104,21 @@ standard_ProcessUtility(Node *parsetree, { RenameStmt *stmt = (RenameStmt *) parsetree; RemoteQueryExecType exec_type; + bool is_temp = false; /* Relation is not set for a schema */ if (stmt->relation) - exec_type = ExecUtilityFindNodes(queryString, - stmt->renameType, - RangeVarGetRelid(stmt->relation, false)); + exec_type = ExecUtilityFindNodes(stmt->renameType, + RangeVarGetRelid(stmt->relation, false), + &is_temp); else exec_type = EXEC_ON_ALL_NODES; ExecUtilityStmtOnNodes(queryString, NULL, false, - exec_type); + exec_type, + is_temp); } #endif ExecRenameStmt((RenameStmt *) parsetree); @@ -1004,19 +1129,21 @@ standard_ProcessUtility(Node *parsetree, if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) { AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree; - RemoteQueryExecType exec_type; + bool is_temp = false; + if (stmt->relation) - exec_type = ExecUtilityFindNodes(queryString, - stmt->objectType, - RangeVarGetRelid(stmt->relation, false)); + exec_type = ExecUtilityFindNodes(stmt->objectType, + RangeVarGetRelid(stmt->relation, false), + &is_temp); else exec_type = EXEC_ON_ALL_NODES; ExecUtilityStmtOnNodes(queryString, NULL, false, - exec_type); + exec_type, + is_temp); } #endif ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree); @@ -1027,7 +1154,7 @@ standard_ProcessUtility(Node *parsetree, #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1045,12 +1172,14 @@ standard_ProcessUtility(Node *parsetree, */ if (isTopLevel) { + bool is_temp = false; AlterTableStmt *stmt = (AlterTableStmt *) parsetree; - RemoteQueryExecType exec_type = ExecUtilityFindNodes(queryString, - stmt->relkind, - RangeVarGetRelid(stmt->relation, false)); + RemoteQueryExecType exec_type; + exec_type = ExecUtilityFindNodes(stmt->relkind, + RangeVarGetRelid(stmt->relation, false), + &is_temp); - stmts = AddRemoteQueryNode(stmts, queryString, exec_type); + stmts = AddRemoteQueryNode(stmts, queryString, exec_type, is_temp); } #endif @@ -1126,7 +1255,7 @@ standard_ProcessUtility(Node *parsetree, } #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1136,6 +1265,7 @@ standard_ProcessUtility(Node *parsetree, { RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES; GrantStmt *stmt = (GrantStmt *) parsetree; + bool is_temp = false; /* Launch GRANT on Coordinator if object is a sequence */ if ((stmt->objtype == ACL_OBJECT_RELATION && @@ -1156,22 +1286,9 @@ standard_ProcessUtility(Node *parsetree, RangeVar *relvar = (RangeVar *) lfirst(cell); Oid relid = RangeVarGetRelid(relvar, false); - if (get_rel_relkind(relid) == RELKIND_SEQUENCE || - get_rel_relkind(relid) == RELKIND_VIEW) - { - /* PGXCTODO: extend that for temporary views and tables */ - if (get_rel_relkind(relid) == RELKIND_SEQUENCE && - IsTempSequence(relid)) - remoteExecType = EXEC_ON_NONE; - else - remoteExecType = EXEC_ON_COORDS; - } - else - { - remoteExecType = EXEC_ON_ALL_NODES; - } + remoteExecType = ExecUtilityFindNodesRelkind(relid, &is_temp); - /* Check if objects can be launched at the same place as 1st one */ + /* Check if object node type corresponds to the first one */ if (first) { type_local = remoteExecType; @@ -1183,11 +1300,11 @@ standard_ProcessUtility(Node *parsetree, ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("PGXC does not support GRANT on multiple object types"), - errdetail("Grant VIEW/SEQUENCE and relations on separate queries"))); + errdetail("Grant VIEW/SEQUENCE/TABLE with separate queries"))); } } } - ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType); + ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType, is_temp); } #endif ExecuteGrantStmt((GrantStmt *) parsetree); @@ -1198,7 +1315,7 @@ standard_ProcessUtility(Node *parsetree, #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1207,7 +1324,7 @@ standard_ProcessUtility(Node *parsetree, #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1260,7 +1377,7 @@ standard_ProcessUtility(Node *parsetree, } #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1272,7 +1389,7 @@ standard_ProcessUtility(Node *parsetree, } #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1280,7 +1397,7 @@ standard_ProcessUtility(Node *parsetree, DefineEnum((CreateEnumStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1299,7 +1416,16 @@ standard_ProcessUtility(Node *parsetree, DefineView((ViewStmt *) parsetree, queryString); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS); + { + /* + * If view is temporary, no need to send this query to other + * remote Coordinators + */ + ViewStmt *stmt = (ViewStmt *) parsetree; + + if (stmt->view->relpersistence != RELPERSISTENCE_TEMP) + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS, false); + } #endif break; @@ -1307,7 +1433,7 @@ standard_ProcessUtility(Node *parsetree, CreateFunction((CreateFunctionStmt *) parsetree, queryString); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1315,7 +1441,7 @@ standard_ProcessUtility(Node *parsetree, AlterFunction((AlterFunctionStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1324,6 +1450,10 @@ standard_ProcessUtility(Node *parsetree, IndexStmt *stmt = (IndexStmt *) parsetree; #ifdef PGXC + Oid relid; + bool is_temp = false; + RemoteQueryExecType exec_type = EXEC_ON_ALL_NODES; + if (stmt->concurrent) { ereport(ERROR, @@ -1331,6 +1461,11 @@ standard_ProcessUtility(Node *parsetree, errmsg("PGXC does not support concurrent INDEX yet"), errdetail("The feature is not currently supported"))); } + + /* INDEX on a temporary table cannot use 2PC at commit */ + relid = RangeVarGetRelid(stmt->relation, true); + if (OidIsValid(relid)) + exec_type = ExecUtilityFindNodes(OBJECT_TABLE, relid, &is_temp); #endif if (stmt->concurrent) @@ -1365,7 +1500,7 @@ standard_ProcessUtility(Node *parsetree, #ifdef PGXC if (IS_PGXC_COORDINATOR && !stmt->isconstraint && !IsConnFromCoord()) ExecUtilityStmtOnNodes(queryString, NULL, - stmt->concurrent, EXEC_ON_ALL_NODES); + stmt->concurrent, exec_type, is_temp); #endif } break; @@ -1377,14 +1512,11 @@ standard_ProcessUtility(Node *parsetree, if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) { RemoteQueryExecType remoteExecType; + bool is_temp; Oid relid = RangeVarGetRelid(((RuleStmt *) parsetree)->relation, false); - if (get_rel_relkind(relid) == RELKIND_VIEW) - remoteExecType = EXEC_ON_COORDS; - else - remoteExecType = EXEC_ON_ALL_NODES; - - ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType); + remoteExecType = ExecUtilityFindNodesRelkind(relid, &is_temp); + ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType, is_temp); } #endif break; @@ -1400,9 +1532,8 @@ standard_ProcessUtility(Node *parsetree, */ CreateSeqStmt *stmt = (CreateSeqStmt *) parsetree; - if (stmt->sequence->relpersistence == RELPERSISTENCE_PERMANENT || - stmt->sequence->relpersistence == RELPERSISTENCE_UNLOGGED) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS); + if (stmt->sequence->relpersistence != RELPERSISTENCE_TEMP) + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS, false); } #endif break; @@ -1420,7 +1551,7 @@ standard_ProcessUtility(Node *parsetree, Oid relid = RangeVarGetRelid(stmt->sequence, false); if (!IsTempSequence(relid)) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS, false); } #endif break; @@ -1448,7 +1579,7 @@ standard_ProcessUtility(Node *parsetree, } #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1461,7 +1592,7 @@ standard_ProcessUtility(Node *parsetree, createdb((CreatedbStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_ALL_NODES, false); #endif break; @@ -1469,7 +1600,7 @@ standard_ProcessUtility(Node *parsetree, AlterDatabase((AlterDatabaseStmt *) parsetree, isTopLevel); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1477,7 +1608,7 @@ standard_ProcessUtility(Node *parsetree, AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1495,7 +1626,7 @@ standard_ProcessUtility(Node *parsetree, /* Clean also remote Coordinators */ sprintf(query, "CLEAN CONNECTION TO ALL FOR DATABASE %s;", stmt->dbname); - ExecUtilityStmtOnNodes(query, NULL, true, EXEC_ON_COORDS); + ExecUtilityStmtOnNodes(query, NULL, true, EXEC_ON_COORDS, false); } #endif @@ -1504,7 +1635,7 @@ standard_ProcessUtility(Node *parsetree, } #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_ALL_NODES, false); #endif break; @@ -1551,7 +1682,7 @@ standard_ProcessUtility(Node *parsetree, } #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_DATANODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_DATANODES, false); #endif break; @@ -1561,7 +1692,7 @@ standard_ProcessUtility(Node *parsetree, cluster((ClusterStmt *) parsetree, isTopLevel); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_DATANODES); + ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_DATANODES, false); #endif break; @@ -1574,7 +1705,7 @@ standard_ProcessUtility(Node *parsetree, * vacuum() pops active snapshot and we can not send it to nodes */ if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_DATANODES); + ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_DATANODES, false); #endif vacuum((VacuumStmt *) parsetree, InvalidOid, true, NULL, false, isTopLevel); @@ -1596,8 +1727,16 @@ standard_ProcessUtility(Node *parsetree, * send this query to backend nodes */ if (!stmt->is_local || !IsTransactionBlock()) - if (PoolManagerSetCommand(stmt->is_local, queryString) < 0) + { + PoolCommandType command_type; + if (stmt->is_local) + command_type = POOL_CMD_LOCAL_SET; + else + command_type = POOL_CMD_GLOBAL_SET; + + if (PoolManagerSetCommand(command_type, queryString) < 0) elog(ERROR, "Postgres-XC: ERROR SET query"); + } } #endif break; @@ -1623,7 +1762,7 @@ standard_ProcessUtility(Node *parsetree, * send this query to backend nodes */ if (!IsTransactionBlock()) - if (PoolManagerSetCommand(false, queryString) < 0) + if (PoolManagerSetCommand(POOL_CMD_GLOBAL_SET, queryString) < 0) elog(ERROR, "Postgres-XC: ERROR DISCARD query"); } #endif @@ -1640,7 +1779,7 @@ standard_ProcessUtility(Node *parsetree, errdetail("The feature is not currently supported"))); if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1661,15 +1800,12 @@ standard_ProcessUtility(Node *parsetree, /* If rule is defined on a view, drop it only on Coordinators */ if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) { - RemoteQueryExecType remoteExecType; + RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES; + bool is_temp = false; Oid relid = RangeVarGetRelid(stmt->relation, false); - if (get_rel_relkind(relid) == RELKIND_VIEW) - remoteExecType = EXEC_ON_COORDS; - else - remoteExecType = EXEC_ON_ALL_NODES; - - ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType); + remoteExecType = ExecUtilityFindNodesRelkind(relid, &is_temp); + ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType, is_temp); } #endif break; @@ -1679,7 +1815,7 @@ standard_ProcessUtility(Node *parsetree, stmt->behavior, stmt->missing_ok); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; default: @@ -1694,7 +1830,7 @@ standard_ProcessUtility(Node *parsetree, CreateProceduralLanguage((CreatePLangStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1702,7 +1838,7 @@ standard_ProcessUtility(Node *parsetree, DropProceduralLanguage((DropPLangStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1713,7 +1849,7 @@ standard_ProcessUtility(Node *parsetree, DefineDomain((CreateDomainStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1724,7 +1860,7 @@ standard_ProcessUtility(Node *parsetree, CreateRole((CreateRoleStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1732,7 +1868,7 @@ standard_ProcessUtility(Node *parsetree, AlterRole((AlterRoleStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1740,7 +1876,7 @@ standard_ProcessUtility(Node *parsetree, AlterRoleSet((AlterRoleSetStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1748,7 +1884,7 @@ standard_ProcessUtility(Node *parsetree, DropRole((DropRoleStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1756,7 +1892,7 @@ standard_ProcessUtility(Node *parsetree, DropOwnedObjects((DropOwnedStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1764,7 +1900,7 @@ standard_ProcessUtility(Node *parsetree, ReassignOwnedObjects((ReassignOwnedStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1778,7 +1914,7 @@ standard_ProcessUtility(Node *parsetree, LockTableCommand((LockStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1810,7 +1946,7 @@ standard_ProcessUtility(Node *parsetree, (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE)); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_DATANODES); + ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_DATANODES, false); #endif break; @@ -1855,7 +1991,7 @@ standard_ProcessUtility(Node *parsetree, #ifdef PGXC if (IS_PGXC_COORDINATOR) ExecUtilityStmtOnNodes(queryString, NULL, - stmt->kind == OBJECT_DATABASE, EXEC_ON_ALL_NODES); + stmt->kind == OBJECT_DATABASE, EXEC_ON_ALL_NODES, false); #endif break; } @@ -1865,7 +2001,7 @@ standard_ProcessUtility(Node *parsetree, CreateConversionCommand((CreateConversionStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1873,7 +2009,7 @@ standard_ProcessUtility(Node *parsetree, CreateCast((CreateCastStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1881,7 +2017,7 @@ standard_ProcessUtility(Node *parsetree, DropCast((DropCastStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1889,7 +2025,7 @@ standard_ProcessUtility(Node *parsetree, DefineOpClass((CreateOpClassStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1897,7 +2033,7 @@ standard_ProcessUtility(Node *parsetree, DefineOpFamily((CreateOpFamilyStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1905,7 +2041,7 @@ standard_ProcessUtility(Node *parsetree, AlterOpFamily((AlterOpFamilyStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1913,7 +2049,7 @@ standard_ProcessUtility(Node *parsetree, RemoveOpClass((RemoveOpClassStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1921,7 +2057,7 @@ standard_ProcessUtility(Node *parsetree, RemoveOpFamily((RemoveOpFamilyStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1929,7 +2065,7 @@ standard_ProcessUtility(Node *parsetree, AlterTSDictionary((AlterTSDictionaryStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; @@ -1937,7 +2073,7 @@ standard_ProcessUtility(Node *parsetree, AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree); #ifdef PGXC if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES, false); #endif break; #ifdef PGXC @@ -1956,7 +2092,7 @@ standard_ProcessUtility(Node *parsetree, CleanConnection((CleanConnStmt *) parsetree); if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_COORDS); + ExecUtilityStmtOnNodes(queryString, NULL, true, EXEC_ON_COORDS, false); break; #endif default: @@ -1975,7 +2111,7 @@ standard_ProcessUtility(Node *parsetree, */ static void ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, - bool force_autocommit, RemoteQueryExecType exec_type) + bool force_autocommit, RemoteQueryExecType exec_type, bool is_temp) { /* Return if query is launched on no nodes */ if (exec_type == EXEC_ON_NONE) @@ -1989,6 +2125,7 @@ ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, step->sql_statement = pstrdup(queryString); step->force_autocommit = force_autocommit; step->exec_type = exec_type; + step->is_temp = is_temp; ExecRemoteUtility(step); pfree(step->sql_statement); pfree(step); @@ -2000,37 +2137,97 @@ ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, * * Determine the list of nodes to launch query on. * This depends on temporary nature of object and object type. - * PGXCTODO: Extend temporary object check for tables. + * Return also a flag indicating if relation is temporary. */ static RemoteQueryExecType -ExecUtilityFindNodes(const char *queryString, - ObjectType object_type, - Oid relid) +ExecUtilityFindNodes(ObjectType object_type, + Oid relid, + bool *is_temp) { - bool is_temp = false; - RemoteQueryExecType remoteExecType = EXEC_ON_NONE; + RemoteQueryExecType exec_type; - /* Check if object is a temporary sequence */ - if (object_type == OBJECT_SEQUENCE || - (object_type == OBJECT_TABLE && - get_rel_relkind(relid) == RELKIND_SEQUENCE)) - is_temp = IsTempSequence(relid); + switch (object_type) + { + case OBJECT_SEQUENCE: + /* Check if object is a temporary sequence */ + if ((*is_temp = IsTempSequence(relid))) + exec_type = EXEC_ON_NONE; + else + exec_type = EXEC_ON_COORDS; + break; + + case OBJECT_TABLE: + /* Do the check on relation kind */ + exec_type = ExecUtilityFindNodesRelkind(relid, is_temp); + break; + + case OBJECT_VIEW: + /* Check if object is a temporary view */ + if ((*is_temp = IsTempTable(relid))) + exec_type = EXEC_ON_NONE; + else + exec_type = EXEC_ON_COORDS; + break; + + case OBJECT_INDEX: + /* Check if given index uses temporary tables */ + if ((*is_temp = IsIndexUsingTempTable(relid))) + exec_type = EXEC_ON_DATANODES; + else + exec_type = EXEC_ON_ALL_NODES; + break; + + default: + *is_temp = false; + exec_type = EXEC_ON_ALL_NODES; + break; + } + + return exec_type; +} - if (!is_temp) +/* + * ExecUtilityFindNodesRelkind + * + * Get node execution and temporary type + * for given relation depending on its relkind + */ +static RemoteQueryExecType +ExecUtilityFindNodesRelkind(Oid relid, bool *is_temp) +{ + char relkind_str = get_rel_relkind(relid); + RemoteQueryExecType exec_type; + + switch (relkind_str) { - remoteExecType = EXEC_ON_ALL_NODES; + case RELKIND_SEQUENCE: + if ((*is_temp = IsTempSequence(relid))) + exec_type = EXEC_ON_NONE; + else + exec_type = EXEC_ON_COORDS; + break; - if (object_type == OBJECT_SEQUENCE || - object_type == OBJECT_VIEW) - remoteExecType = EXEC_ON_COORDS; - else if (object_type == OBJECT_TABLE) - { - if (get_rel_relkind(relid) == RELKIND_SEQUENCE) - remoteExecType = EXEC_ON_COORDS; - } + case RELKIND_RELATION: + if ((*is_temp = IsTempTable(relid))) + exec_type = EXEC_ON_DATANODES; + else + exec_type = EXEC_ON_ALL_NODES; + break; + + case RELKIND_VIEW: + if ((*is_temp = IsTempTable(relid))) + exec_type = EXEC_ON_NONE; + else + exec_type = EXEC_ON_COORDS; + break; + + default: + *is_temp = false; + exec_type = EXEC_ON_ALL_NODES; + break; } - return remoteExecType; + return exec_type; } #endif diff --git a/src/include/commands/comment.h b/src/include/commands/comment.h index 1b12e81bdd..b3d8da156f 100644 --- a/src/include/commands/comment.h +++ b/src/include/commands/comment.h @@ -41,4 +41,8 @@ extern void CreateSharedComments(Oid oid, Oid classoid, char *comment); extern char *GetComment(Oid oid, Oid classoid, int32 subid); +#ifdef PGXC +extern Oid GetCommentObjectId(CommentStmt *stmt); +#endif + #endif /* COMMENT_H */ diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 3f971eb218..7d46ede251 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -70,5 +70,13 @@ extern void AtEOXact_on_commit_actions(bool isCommit); extern void AtEOSubXact_on_commit_actions(bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid); +#ifdef PGXC +extern bool IsTempTable(Oid relid); +extern bool IsIndexUsingTempTable(Oid relid); +extern bool IsOnCommitActions(void); +extern void DropTableThrowErrorExternal(RangeVar *relation, + ObjectType removeType, + bool missing_ok); +#endif #endif /* TABLECMDS_H */ diff --git a/src/include/pgxc/execRemote.h b/src/include/pgxc/execRemote.h index 48d23ca399..cf25c2d966 100644 --- a/src/include/pgxc/execRemote.h +++ b/src/include/pgxc/execRemote.h @@ -162,5 +162,7 @@ extern int ParamListToDataRow(ParamListInfo params, char** result); extern void ExecCloseRemoteStatement(const char *stmt_name, List *nodelist); +extern void ExecSetTempObjectIncluded(void); + extern int primary_data_node; #endif diff --git a/src/include/pgxc/planner.h b/src/include/pgxc/planner.h index edb2174dbf..efba3c4e09 100644 --- a/src/include/pgxc/planner.h +++ b/src/include/pgxc/planner.h @@ -106,6 +106,8 @@ typedef struct * plan. So, don't change this once set. */ RemoteQueryExecType exec_type; + bool is_temp; /* determine if this remote node is based + * on a temporary objects (no 2PC) */ /* Support for parameters */ char *paramval_data; /* parameter data, format is like in BIND */ @@ -147,6 +149,7 @@ extern bool IsHashDistributable(Oid col_type); extern bool IsJoinReducible(RemoteQuery *innernode, RemoteQuery *outernode, List *rtable_list, JoinPath *join_path, JoinReduceInfo *join_info); -extern List *AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType remoteExecType); +extern List *AddRemoteQueryNode(List *stmts, const char *queryString, + RemoteQueryExecType remoteExecType, bool is_temp); #endif /* PGXCPLANNER_H */ diff --git a/src/include/pgxc/poolmgr.h b/src/include/pgxc/poolmgr.h index 79397687da..bf74a6eb49 100644 --- a/src/include/pgxc/poolmgr.h +++ b/src/include/pgxc/poolmgr.h @@ -23,6 +23,28 @@ #define MAX_IDLE_TIME 60 +/* + * List of flags related to pooler connection clean up when disconnecting + * a session or relaeasing handles. + * When Local SET commands (POOL_CMD_LOCAL_SET) are used, local parameter + * string is cleaned by the node commit itself. + * When global SET commands (POOL_CMD_GLOBAL_SET) are used, "RESET ALL" + * command is sent down to activated nodes to at session end. At the end + * of a transaction, connections using global SET commands are not sent + * back to pool. + * When temporary object commands are used (POOL_CMD_TEMP), "DISCARD ALL" + * query is sent down to nodes whose connection is activated at the end of + * a session. + * At the end of a transaction, a session using either temporary objects + * or global session parameters has its connections not sent back to pool. + */ +typedef enum +{ + POOL_CMD_TEMP, /* Temporary object flag */ + POOL_CMD_LOCAL_SET, /* Local SET flag */ + POOL_CMD_GLOBAL_SET /* Global SET flag */ +} PoolCommandType; + /* TODO move? */ typedef struct { @@ -73,6 +95,7 @@ typedef struct PGXCNodePoolSlot **coord_connections; /* one for each Coordinator */ char *session_params; char *local_params; + bool is_temp; /* Temporary objects used for this pool session? */ } PoolAgent; /* Handle to the pool manager (Session's side) */ @@ -136,7 +159,7 @@ extern void PoolManagerConnect(PoolHandle *handle, const char *database, const c * and stored in pooler agent to be replayed when new connections * are requested. */ -extern int PoolManagerSetCommand(bool is_local, const char *set_command); +extern int PoolManagerSetCommand(PoolCommandType command_type, const char *set_command); /* Get pooled connections */ extern int *PoolManagerGetConnections(List *datanodelist, List *coordlist); diff --git a/src/test/regress/expected/cluster_1.out b/src/test/regress/expected/cluster_1.out index 8017e1e351..f5f24ad093 100644 --- a/src/test/regress/expected/cluster_1.out +++ b/src/test/regress/expected/cluster_1.out @@ -373,19 +373,17 @@ SELECT * FROM clustertest ORDER BY 1; -- check that temp tables can be clustered create temp table clstr_temp (col1 int primary key, col2 text); -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "clstr_temp_pkey" for table "clstr_temp" insert into clstr_temp values (2, 'two'), (1, 'one'); -ERROR: relation "clstr_temp" does not exist -LINE 1: insert into clstr_temp values (2, 'two'), (1, 'one'); - ^ cluster clstr_temp using clstr_temp_pkey; -ERROR: relation "clstr_temp" does not exist -select * from clstr_temp; -ERROR: relation "clstr_temp" does not exist -LINE 1: select * from clstr_temp; - ^ +select * from clstr_temp order by 1; + col1 | col2 +------+------ + 1 | one + 2 | two +(2 rows) + drop table clstr_temp; -ERROR: table "clstr_temp" does not exist -- clean up \c - DROP TABLE clustertest; diff --git a/src/test/regress/expected/combocid_1.out b/src/test/regress/expected/combocid_1.out index eab70859b9..dbd2dc27cb 100644 --- a/src/test/regress/expected/combocid_1.out +++ b/src/test/regress/expected/combocid_1.out @@ -2,39 +2,29 @@ -- Tests for some likely failure cases with combo cmin/cmax mechanism -- CREATE TEMP TABLE combocidtest (foobar int); -ERROR: PG-XC does not yet support temporary tables BEGIN; -- a few dummy ops to push up the CommandId counter INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: relation "combocidtest" does not exist -LINE 1: INSERT INTO combocidtest SELECT 1 LIMIT 0; - ^ INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest VALUES (1); -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest VALUES (2); -ERROR: current transaction is aborted, commands ignored until end of transaction block SELECT ctid,cmin,* FROM combocidtest ORDER BY ctid; -ERROR: current transaction is aborted, commands ignored until end of transaction block + ctid | cmin | foobar +-------+------+-------- + (0,1) | 0 | 1 + (0,1) | 0 | 2 +(2 rows) + SAVEPOINT s1; -ERROR: current transaction is aborted, commands ignored until end of transaction block +ERROR: SAVEPOINT is not yet supported. UPDATE combocidtest SET foobar = foobar + 10; ERROR: current transaction is aborted, commands ignored until end of transaction block -- here we should see only updated tuples @@ -48,57 +38,48 @@ ERROR: current transaction is aborted, commands ignored until end of transactio COMMIT; -- combo data is not there anymore, but should still see tuples SELECT ctid,cmin,* FROM combocidtest; -ERROR: relation "combocidtest" does not exist -LINE 1: SELECT ctid,cmin,* FROM combocidtest; - ^ + ctid | cmin | foobar +------+------+-------- +(0 rows) + -- Test combo cids with portals BEGIN; INSERT INTO combocidtest VALUES (333); -ERROR: relation "combocidtest" does not exist -LINE 1: INSERT INTO combocidtest VALUES (333); - ^ DECLARE c CURSOR FOR SELECT ctid,cmin,* FROM combocidtest ORDER BY ctid; -ERROR: current transaction is aborted, commands ignored until end of transaction block DELETE FROM combocidtest; -ERROR: current transaction is aborted, commands ignored until end of transaction block FETCH ALL FROM c; -ERROR: current transaction is aborted, commands ignored until end of transaction block + ctid | cmin | foobar +------+------+-------- +(0 rows) + ROLLBACK; SELECT ctid,cmin,* FROM combocidtest ORDER BY ctid; -ERROR: relation "combocidtest" does not exist -LINE 1: SELECT ctid,cmin,* FROM combocidtest ORDER BY ctid; - ^ + ctid | cmin | foobar +------+------+-------- +(0 rows) + -- check behavior with locked tuples BEGIN; -- a few dummy ops to push up the CommandId counter INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: relation "combocidtest" does not exist -LINE 1: INSERT INTO combocidtest SELECT 1 LIMIT 0; - ^ INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest SELECT 1 LIMIT 0; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO combocidtest VALUES (444); -ERROR: current transaction is aborted, commands ignored until end of transaction block SELECT ctid,cmin,* FROM combocidtest ORDER BY ctid; -ERROR: current transaction is aborted, commands ignored until end of transaction block + ctid | cmin | foobar +-------+------+-------- + (0,3) | 0 | 444 +(1 row) + SAVEPOINT s1; -ERROR: current transaction is aborted, commands ignored until end of transaction block +ERROR: SAVEPOINT is not yet supported. -- this doesn't affect cmin SELECT ctid,cmin,* FROM combocidtest FOR UPDATE; ERROR: current transaction is aborted, commands ignored until end of transaction block @@ -115,6 +96,7 @@ SELECT ctid,cmin,* FROM combocidtest ORDER BY ctid; ERROR: current transaction is aborted, commands ignored until end of transaction block COMMIT; SELECT ctid,cmin,* FROM combocidtest ORDER BY ctid; -ERROR: relation "combocidtest" does not exist -LINE 1: SELECT ctid,cmin,* FROM combocidtest ORDER BY ctid; - ^ + ctid | cmin | foobar +------+------+-------- +(0 rows) + diff --git a/src/test/regress/expected/copy2_1.out b/src/test/regress/expected/copy2_1.out index 9ff656ca33..d9b149e37f 100644 --- a/src/test/regress/expected/copy2_1.out +++ b/src/test/regress/expected/copy2_1.out @@ -167,78 +167,69 @@ CREATE TEMP TABLE y ( col1 text, col2 text ); -ERROR: PG-XC does not yet support temporary tables INSERT INTO y VALUES ('Jackson, Sam', E'\\h'); -ERROR: relation "y" does not exist -LINE 1: INSERT INTO y VALUES ('Jackson, Sam', E'\\h'); - ^ INSERT INTO y VALUES ('It is "perfect".',E'\t'); -ERROR: relation "y" does not exist -LINE 1: INSERT INTO y VALUES ('It is "perfect".',E'\t'); - ^ INSERT INTO y VALUES ('', NULL); -ERROR: relation "y" does not exist -LINE 1: INSERT INTO y VALUES ('', NULL); - ^ COPY y TO stdout WITH CSV; -ERROR: relation "y" does not exist +"Jackson, Sam",\h +"It is ""perfect"".", +"", COPY y TO stdout WITH CSV QUOTE '''' DELIMITER '|'; -ERROR: relation "y" does not exist +Jackson, Sam|\h +It is "perfect".| +''| COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\' ENCODING 'sql_ascii'; -ERROR: relation "y" does not exist +"Jackson, Sam","\\h" +"It is \"perfect\"."," " +"", COPY y TO stdout WITH CSV FORCE QUOTE *; -ERROR: relation "y" does not exist +"Jackson, Sam",\h +"It is ""perfect"".", +"", -- Repeat above tests with new 9.0 option syntax COPY y TO stdout (FORMAT CSV); -ERROR: relation "y" does not exist +"Jackson, Sam",\h +"It is ""perfect"".", +"", COPY y TO stdout (FORMAT CSV, QUOTE '''', DELIMITER '|'); -ERROR: relation "y" does not exist +Jackson, Sam|\h +It is "perfect".| +''| COPY y TO stdout (FORMAT CSV, FORCE_QUOTE (col2), ESCAPE E'\\'); -ERROR: relation "y" does not exist +"Jackson, Sam","\\h" +"It is \"perfect\"."," " +"", COPY y TO stdout (FORMAT CSV, FORCE_QUOTE *); -ERROR: relation "y" does not exist +"Jackson, Sam",\h +"It is ""perfect"".", +"", \copy y TO stdout (FORMAT CSV) -ERROR: relation "y" does not exist -\copy: ERROR: relation "y" does not exist +"Jackson, Sam",\h +"It is ""perfect"".", +"", \copy y TO stdout (FORMAT CSV, QUOTE '''', DELIMITER '|') -ERROR: relation "y" does not exist -\copy: ERROR: relation "y" does not exist +Jackson, Sam|\h +It is "perfect".| +''| \copy y TO stdout (FORMAT CSV, FORCE_QUOTE (col2), ESCAPE E'\\') -ERROR: relation "y" does not exist -\copy: ERROR: relation "y" does not exist +"Jackson, Sam","\\h" +"It is \"perfect\"."," " +"", \copy y TO stdout (FORMAT CSV, FORCE_QUOTE *) -ERROR: relation "y" does not exist -\copy: ERROR: relation "y" does not exist +"Jackson, Sam",\h +"It is ""perfect"".", +"", --test that we read consecutive LFs properly CREATE TEMP TABLE testnl (a int, b text, c int); -ERROR: PG-XC does not yet support temporary tables COPY testnl FROM stdin CSV; -ERROR: relation "testnl" does not exist -1,"a field with two LFs - -inside",2 -\. -invalid command \. -- test end of copy marker CREATE TEMP TABLE testeoc (a text); -ERROR: syntax error at or near "1" -LINE 1: 1,"a field with two LFs - ^ COPY testeoc FROM stdin CSV; -ERROR: relation "testeoc" does not exist +COPY testeoc TO stdout CSV; a\. -invalid command \. \.b -invalid command \.b c\.d -invalid command \.d "\." -\. -invalid command \. -COPY testeoc TO stdout CSV; -ERROR: syntax error at or near "a" -LINE 1: a - ^ DROP TABLE x, y; ERROR: table "x" does not exist DROP FUNCTION fn_x_before(); diff --git a/src/test/regress/expected/domain_1.out b/src/test/regress/expected/domain_1.out index 6c158f2c66..f2f45379d6 100644 --- a/src/test/regress/expected/domain_1.out +++ b/src/test/regress/expected/domain_1.out @@ -438,33 +438,18 @@ ERROR: value for domain dtop violates check constraint "dinter_check" select 'xz23'::dtop; -- fail ERROR: value for domain dtop violates check constraint "dtop_check" create temp table dtest(f1 dtop); -ERROR: PG-XC does not yet support temporary tables insert into dtest values('x123'); -ERROR: relation "dtest" does not exist -LINE 1: insert into dtest values('x123'); - ^ insert into dtest values('x1234'); -- fail, implicit coercion -ERROR: relation "dtest" does not exist -LINE 1: insert into dtest values('x1234'); - ^ +ERROR: value too long for type character varying(4) insert into dtest values('y1234'); -- fail, implicit coercion -ERROR: relation "dtest" does not exist -LINE 1: insert into dtest values('y1234'); - ^ +ERROR: value too long for type character varying(4) insert into dtest values('y123'); -- fail -ERROR: relation "dtest" does not exist -LINE 1: insert into dtest values('y123'); - ^ +ERROR: value for domain dtop violates check constraint "dinter_check" insert into dtest values('yz23'); -- fail -ERROR: relation "dtest" does not exist -LINE 1: insert into dtest values('yz23'); - ^ +ERROR: value for domain dtop violates check constraint "dinter_check" insert into dtest values('xz23'); -- fail -ERROR: relation "dtest" does not exist -LINE 1: insert into dtest values('xz23'); - ^ +ERROR: value for domain dtop violates check constraint "dtop_check" drop table dtest; -ERROR: table "dtest" does not exist drop domain vchar4 cascade; NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to type dinter @@ -636,27 +621,19 @@ select array[1,2]::orderedpair; select array[2,1]::orderedpair; -- fail ERROR: value for domain orderedpair violates check constraint "orderedpair_check" create temp table op (f1 orderedpair); -ERROR: PG-XC does not yet support temporary tables insert into op values (array[1,2]); -ERROR: relation "op" does not exist -LINE 1: insert into op values (array[1,2]); - ^ insert into op values (array[2,1]); -- fail -ERROR: relation "op" does not exist -LINE 1: insert into op values (array[2,1]); - ^ +ERROR: value for domain orderedpair violates check constraint "orderedpair_check" update op set f1[2] = 3; -ERROR: relation "op" does not exist -LINE 1: update op set f1[2] = 3; - ^ +ERROR: syntax error at or near ":=" update op set f1[2] = 0; -- fail -ERROR: relation "op" does not exist -LINE 1: update op set f1[2] = 0; - ^ +ERROR: syntax error at or near ":=" select * from op; -ERROR: relation "op" does not exist -LINE 1: select * from op; - ^ + f1 +------- + {1,2} +(1 row) + create or replace function array_elem_check(int) returns int as $$ declare x orderedpair := '{1,2}'; diff --git a/src/test/regress/expected/foreign_key_1.out b/src/test/regress/expected/foreign_key_1.out index 560b5e9f70..8dc155a63a 100644 --- a/src/test/regress/expected/foreign_key_1.out +++ b/src/test/regress/expected/foreign_key_1.out @@ -1125,7 +1125,8 @@ CREATE TEMP TABLE pktable ( id3 REAL UNIQUE, UNIQUE(id1, id2, id3) ); -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable" +ERROR: Unique index of partitioned table must contain the hash/modulo distribution column. CREATE TEMP TABLE fktable ( x1 INT4 REFERENCES pktable(id1), x2 VARCHAR(4) REFERENCES pktable(id2), @@ -1197,7 +1198,7 @@ CREATE TEMP TABLE pktable ( id int primary key, other int ); -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable" CREATE TEMP TABLE fktable ( id int primary key, fk int references pktable deferrable initially deferred @@ -1205,9 +1206,6 @@ CREATE TEMP TABLE fktable ( ERROR: Postgres-XC does not support DEFERRED constraints yet DETAIL: The feature is not currently supported INSERT INTO pktable VALUES (5, 10); -ERROR: relation "pktable" does not exist -LINE 1: INSERT INTO pktable VALUES (5, 10); - ^ BEGIN; -- doesn't match PK, but no error yet INSERT INTO fktable VALUES (0, 20); @@ -1272,26 +1270,17 @@ CREATE TEMP TABLE users ( id INT PRIMARY KEY, name VARCHAR NOT NULL ); -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "users_pkey" for table "users" INSERT INTO users VALUES (1, 'Jozko'); -ERROR: relation "users" does not exist -LINE 1: INSERT INTO users VALUES (1, 'Jozko'); - ^ INSERT INTO users VALUES (2, 'Ferko'); -ERROR: relation "users" does not exist -LINE 1: INSERT INTO users VALUES (2, 'Ferko'); - ^ INSERT INTO users VALUES (3, 'Samko'); -ERROR: relation "users" does not exist -LINE 1: INSERT INTO users VALUES (3, 'Samko'); - ^ CREATE TEMP TABLE tasks ( id INT PRIMARY KEY, owner INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL, worker INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL, checked_by INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL ); -ERROR: relation "users" does not exist +ERROR: Hash/Modulo distributed table must include distribution column in index INSERT INTO tasks VALUES (1,1,NULL,NULL); ERROR: relation "tasks" does not exist LINE 1: INSERT INTO tasks VALUES (1,1,NULL,NULL); @@ -1309,17 +1298,12 @@ ERROR: relation "tasks" does not exist LINE 1: SELECT * FROM tasks ORDER BY 1, 2, 3,4; ^ UPDATE users SET id = 4 WHERE id = 3; -ERROR: relation "users" does not exist -LINE 1: UPDATE users SET id = 4 WHERE id = 3; - ^ +ERROR: Partition column can't be updated in current version SELECT * FROM tasks ORDER BY 1, 2, 3,4; ERROR: relation "tasks" does not exist LINE 1: SELECT * FROM tasks ORDER BY 1, 2, 3,4; ^ DELETE FROM users WHERE id = 4; -ERROR: relation "users" does not exist -LINE 1: DELETE FROM users WHERE id = 4; - ^ SELECT * FROM tasks ORDER BY 1, 2, 3,4; ERROR: relation "tasks" does not exist LINE 1: SELECT * FROM tasks ORDER BY 1, 2, 3,4; diff --git a/src/test/regress/expected/functional_deps_1.out b/src/test/regress/expected/functional_deps_1.out index 4fa16821b1..24920e72a5 100644 --- a/src/test/regress/expected/functional_deps_1.out +++ b/src/test/regress/expected/functional_deps_1.out @@ -6,14 +6,15 @@ CREATE TEMP TABLE articles ( body text UNIQUE, created date ); -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "articles_pkey" for table "articles" +ERROR: Unique index of partitioned table must contain the hash/modulo distribution column. CREATE TEMP TABLE articles_in_category ( article_id int, category_id int, changed date, PRIMARY KEY (article_id, category_id) ); -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "articles_in_category_pkey" for table "articles_in_category" -- test functional dependencies based on primary keys/unique constraints -- base tables -- group by primary key (OK) @@ -96,32 +97,29 @@ LINE 2: FROM articles AS a JOIN articles_in_category AS aic ON a.id ... ^ -- example from documentation CREATE TEMP TABLE products (product_id int, name text, price numeric); -ERROR: PG-XC does not yet support temporary tables CREATE TEMP TABLE sales (product_id int, units int); -ERROR: PG-XC does not yet support temporary tables -- OK SELECT product_id, p.name, (sum(s.units) * p.price) AS sales FROM products p LEFT JOIN sales s USING (product_id) GROUP BY product_id, p.name, p.price; -ERROR: relation "products" does not exist -LINE 2: FROM products p LEFT JOIN sales s USING (product_id) - ^ + product_id | name | sales +------------+------+------- +(0 rows) + -- fail SELECT product_id, p.name, (sum(s.units) * p.price) AS sales FROM products p LEFT JOIN sales s USING (product_id) GROUP BY product_id; -ERROR: relation "products" does not exist -LINE 2: FROM products p LEFT JOIN sales s USING (product_id) - ^ +ERROR: column "p.name" must appear in the GROUP BY clause or be used in an aggregate function +LINE 1: SELECT product_id, p.name, (sum(s.units) * p.price) AS sales + ^ ALTER TABLE products ADD PRIMARY KEY (product_id); -ERROR: relation "products" does not exist +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "products_pkey" for table "products" -- OK now SELECT product_id, p.name, (sum(s.units) * p.price) AS sales FROM products p LEFT JOIN sales s USING (product_id) GROUP BY product_id; -ERROR: relation "products" does not exist -LINE 2: FROM products p LEFT JOIN sales s USING (product_id) - ^ +ERROR: column "group_2.name_1_2_1" must appear in the GROUP BY clause or be used in an aggregate function -- Drupal example, http://drupal.org/node/555530 CREATE TEMP TABLE node ( nid SERIAL, @@ -144,7 +142,8 @@ CREATE TEMP TABLE users ( PRIMARY KEY (uid), UNIQUE (name) ); -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "users_pkey" for table "users" +ERROR: Unique index of partitioned table must contain the hash/modulo distribution column. -- OK SELECT u.uid, u.name FROM node n INNER JOIN users u ON u.uid = n.uid @@ -195,7 +194,6 @@ LINE 3: FROM articles AS a JOIN articles_in_category AS aic ON a.id ... ALTER TABLE articles DROP CONSTRAINT articles_pkey RESTRICT; -- fail ERROR: relation "articles" does not exist ALTER TABLE articles_in_category DROP CONSTRAINT articles_in_category_pkey RESTRICT; --fail -ERROR: relation "articles_in_category" does not exist DROP VIEW fdv2; ERROR: view "fdv2" does not exist -- nested queries diff --git a/src/test/regress/expected/guc_1.out b/src/test/regress/expected/guc_1.out index 39790cc262..42e7e37037 100644 --- a/src/test/regress/expected/guc_1.out +++ b/src/test/regress/expected/guc_1.out @@ -416,11 +416,11 @@ SELECT '2006-08-13 12:34:56'::timestamptz; -- Test DISCARD TEMP -- CREATE TEMP TABLE reset_test ( data text ) ON COMMIT DELETE ROWS; -ERROR: PG-XC does not yet support temporary tables SELECT relname FROM pg_class WHERE relname = 'reset_test'; - relname ---------- -(0 rows) + relname +------------ + reset_test +(1 row) DISCARD TEMP; SELECT relname FROM pg_class WHERE relname = 'reset_test'; @@ -437,7 +437,6 @@ PREPARE foo AS SELECT 1; LISTEN foo_event; SET vacuum_cost_delay = 13; CREATE TEMP TABLE tmp_foo (data text) ON COMMIT DELETE ROWS; -ERROR: PG-XC does not yet support temporary tables CREATE ROLE temp_reset_user; SET SESSION AUTHORIZATION temp_reset_user; -- look changes @@ -468,7 +467,8 @@ SHOW vacuum_cost_delay; SELECT relname from pg_class where relname = 'tmp_foo'; relname --------- -(0 rows) + tmp_foo +(1 row) SELECT current_user = 'temp_reset_user'; ?column? diff --git a/src/test/regress/expected/polymorphism_1.out b/src/test/regress/expected/polymorphism_1.out index d78b7ed1e9..48e4dc6824 100644 --- a/src/test/regress/expected/polymorphism_1.out +++ b/src/test/regress/expected/polymorphism_1.out @@ -344,136 +344,205 @@ CREATE AGGREGATE mysum2(anyelement,anyelement) (SFUNC = sum3, STYPE = anyelement, INITCOND = '0'); -- create test data for polymorphic aggregates create temp table t(f1 int, f2 int[], f3 text); -ERROR: PG-XC does not yet support temporary tables insert into t values(1,array[1],'a'); -ERROR: relation "t" does not exist -LINE 1: insert into t values(1,array[1],'a'); - ^ insert into t values(1,array[11],'b'); -ERROR: relation "t" does not exist -LINE 1: insert into t values(1,array[11],'b'); - ^ insert into t values(1,array[111],'c'); -ERROR: relation "t" does not exist -LINE 1: insert into t values(1,array[111],'c'); - ^ insert into t values(2,array[2],'a'); -ERROR: relation "t" does not exist -LINE 1: insert into t values(2,array[2],'a'); - ^ insert into t values(2,array[22],'b'); -ERROR: relation "t" does not exist -LINE 1: insert into t values(2,array[22],'b'); - ^ insert into t values(2,array[222],'c'); -ERROR: relation "t" does not exist -LINE 1: insert into t values(2,array[222],'c'); - ^ insert into t values(3,array[3],'a'); -ERROR: relation "t" does not exist -LINE 1: insert into t values(3,array[3],'a'); - ^ insert into t values(3,array[3],'b'); -ERROR: relation "t" does not exist -LINE 1: insert into t values(3,array[3],'b'); - ^ -- test the successfully created polymorphic aggregates select f3, myaggp01a(*) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp01a(*) from t group by f3 order by f3; - ^ + f3 | myaggp01a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggp03a(*) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp03a(*) from t group by f3 order by f3; - ^ + f3 | myaggp03a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggp03b(*) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp03b(*) from t group by f3 order by f3; - ^ + f3 | myaggp03b +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggp05a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp05a(f1) from t group by f3 order by f3; - ^ + f3 | myaggp05a +----+----------- + a | {3,2,1} + b | {3,2,1} + c | {1,2} +(3 rows) + select f3, myaggp06a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp06a(f1) from t group by f3 order by f3; - ^ + f3 | myaggp06a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggp08a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp08a(f1) from t group by f3 order by f3; - ^ + f3 | myaggp08a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggp09a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp09a(f1) from t group by f3 order by f3; - ^ + f3 | myaggp09a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggp09b(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp09b(f1) from t group by f3 order by f3; - ^ + f3 | myaggp09b +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggp10a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp10a(f1) from t group by f3 order by f3; - ^ + f3 | myaggp10a +----+----------- + a | {3,2,1} + b | {3,2,1} + c | {1,2} +(3 rows) + select f3, myaggp10b(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp10b(f1) from t group by f3 order by f3; - ^ + f3 | myaggp10b +----+----------- + a | {3,2,1} + b | {3,2,1} + c | {1,2} +(3 rows) + select f3, myaggp20a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp20a(f1) from t group by f3 order by f3; - ^ + f3 | myaggp20a +----+----------- + a | {3,2,1} + b | {3,2,1} + c | {1,2} +(3 rows) + select f3, myaggp20b(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggp20b(f1) from t group by f3 order by f3; - ^ + f3 | myaggp20b +----+----------- + a | {3,2,1} + b | {3,2,1} + c | {1,2} +(3 rows) + select f3, myaggn01a(*) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn01a(*) from t group by f3 order by f3; - ^ + f3 | myaggn01a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggn01b(*) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn01b(*) from t group by f3 order by f3; - ^ + f3 | myaggn01b +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggn03a(*) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn03a(*) from t group by f3 order by f3; - ^ + f3 | myaggn03a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggn05a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn05a(f1) from t group by f3 order by f3; - ^ + f3 | myaggn05a +----+----------- + a | {3,2,1} + b | {3,2,1} + c | {1,2} +(3 rows) + select f3, myaggn05b(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn05b(f1) from t group by f3 order by f3; - ^ + f3 | myaggn05b +----+----------- + a | {3,2,1} + b | {3,2,1} + c | {1,2} +(3 rows) + select f3, myaggn06a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn06a(f1) from t group by f3 order by f3; - ^ + f3 | myaggn06a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggn06b(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn06b(f1) from t group by f3 order by f3; - ^ + f3 | myaggn06b +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggn08a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn08a(f1) from t group by f3 order by f3; - ^ + f3 | myaggn08a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggn08b(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn08b(f1) from t group by f3 order by f3; - ^ + f3 | myaggn08b +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggn09a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn09a(f1) from t group by f3 order by f3; - ^ + f3 | myaggn09a +----+----------- + a | {} + b | {} + c | {} +(3 rows) + select f3, myaggn10a(f1) from t group by f3 order by f3; -ERROR: relation "t" does not exist -LINE 1: select f3, myaggn10a(f1) from t group by f3 order by f3; - ^ + f3 | myaggn10a +----+----------- + a | {2,1,3} + b | {3,1,2} + c | {2,1} +(3 rows) + select mysum2(f1, f1 + 1) from t; -ERROR: relation "t" does not exist -LINE 1: select mysum2(f1, f1 + 1) from t; - ^ + mysum2 +-------- + 38 +(1 row) + -- test inlining of polymorphic SQL functions create function bleat(int) returns int as $$ begin diff --git a/src/test/regress/expected/returning_1.out b/src/test/regress/expected/returning_1.out index c620a6a233..bbf24a7db2 100644 --- a/src/test/regress/expected/returning_1.out +++ b/src/test/regress/expected/returning_1.out @@ -77,7 +77,7 @@ LINE 1: SELECT * FROM foo ORDER BY f1; ^ -- Check inheritance cases CREATE TEMP TABLE foochild (fc int) INHERITS (foo); -ERROR: PG-XC does not yet support temporary tables +ERROR: relation "foo" does not exist INSERT INTO foochild VALUES(123,'child',999,-123); ERROR: relation "foochild" does not exist LINE 1: INSERT INTO foochild VALUES(123,'child',999,-123); @@ -220,19 +220,9 @@ LINE 1: SELECT * FROM voo ORDER BY f1; ^ -- Try a join case CREATE TEMP TABLE joinme (f2j text, other int); -ERROR: PG-XC does not yet support temporary tables INSERT INTO joinme VALUES('more', 12345); -ERROR: relation "joinme" does not exist -LINE 1: INSERT INTO joinme VALUES('more', 12345); - ^ INSERT INTO joinme VALUES('zoo2', 54321); -ERROR: relation "joinme" does not exist -LINE 1: INSERT INTO joinme VALUES('zoo2', 54321); - ^ INSERT INTO joinme VALUES('other', 0); -ERROR: relation "joinme" does not exist -LINE 1: INSERT INTO joinme VALUES('other', 0); - ^ CREATE TEMP VIEW joinview AS SELECT foo.*, other FROM foo JOIN joinme ON (f2 = f2j); ERROR: relation "foo" does not exist diff --git a/src/test/regress/expected/rowtypes_1.out b/src/test/regress/expected/rowtypes_1.out index 1af80a0a62..b87c710125 100644 --- a/src/test/regress/expected/rowtypes_1.out +++ b/src/test/regress/expected/rowtypes_1.out @@ -4,7 +4,6 @@ -- Make both a standalone composite type and a table rowtype create type complex as (r float8, i float8); create temp table fullname (first text, last text); -ERROR: PG-XC does not yet support temporary tables -- Nested composite create type quad as (c1 complex, c2 complex); -- Some simple tests of I/O conversions and row construction @@ -15,111 +14,114 @@ select (1.1,2.2)::complex, row((3.3,4.4),(5.5,null))::quad; (1 row) select row('Joe', 'Blow')::fullname, '(Joe,Blow)'::fullname; -ERROR: type "fullname" does not exist -LINE 1: select row('Joe', 'Blow')::fullname, '(Joe,Blow)'::fullname; - ^ + row | fullname +------------+------------ + (Joe,Blow) | (Joe,Blow) +(1 row) + select '(Joe,von Blow)'::fullname, '(Joe,d''Blow)'::fullname; -ERROR: type "fullname" does not exist -LINE 1: select '(Joe,von Blow)'::fullname, '(Joe,d''Blow)'::fullname... - ^ + fullname | fullname +------------------+-------------- + (Joe,"von Blow") | (Joe,d'Blow) +(1 row) + select '(Joe,"von""Blow")'::fullname, E'(Joe,d\\\\Blow)'::fullname; -ERROR: type "fullname" does not exist -LINE 1: select '(Joe,"von""Blow")'::fullname, E'(Joe,d\\\\Blow)'::fu... - ^ + fullname | fullname +-------------------+----------------- + (Joe,"von""Blow") | (Joe,"d\\Blow") +(1 row) + select '(Joe,"Blow,Jr")'::fullname; -ERROR: type "fullname" does not exist -LINE 1: select '(Joe,"Blow,Jr")'::fullname; - ^ + fullname +----------------- + (Joe,"Blow,Jr") +(1 row) + select '(Joe,)'::fullname; -- ok, null 2nd column -ERROR: type "fullname" does not exist -LINE 1: select '(Joe,)'::fullname; - ^ + fullname +---------- + (Joe,) +(1 row) + select '(Joe)'::fullname; -- bad -ERROR: type "fullname" does not exist +ERROR: malformed record literal: "(Joe)" LINE 1: select '(Joe)'::fullname; - ^ + ^ +DETAIL: Too few columns. select '(Joe,,)'::fullname; -- bad -ERROR: type "fullname" does not exist +ERROR: malformed record literal: "(Joe,,)" LINE 1: select '(Joe,,)'::fullname; - ^ + ^ +DETAIL: Too many columns. create temp table quadtable(f1 int, q quad); -ERROR: PG-XC does not yet support temporary tables insert into quadtable values (1, ((3.3,4.4),(5.5,6.6))); -ERROR: relation "quadtable" does not exist -LINE 1: insert into quadtable values (1, ((3.3,4.4),(5.5,6.6))); - ^ insert into quadtable values (2, ((null,4.4),(5.5,6.6))); -ERROR: relation "quadtable" does not exist -LINE 1: insert into quadtable values (2, ((null,4.4),(5.5,6.6))); - ^ select * from quadtable order by f1, q; -ERROR: relation "quadtable" does not exist -LINE 1: select * from quadtable order by f1, q; - ^ + f1 | q +----+--------------------------- + 1 | ("(3.3,4.4)","(5.5,6.6)") + 2 | ("(,4.4)","(5.5,6.6)") +(2 rows) + select f1, q.c1 from quadtable; -- fails, q is a table reference -ERROR: relation "quadtable" does not exist +ERROR: missing FROM-clause entry for table "q" LINE 1: select f1, q.c1 from quadtable; - ^ + ^ select f1, (q).c1, (qq.q).c1.i from quadtable qq order by 1; -ERROR: relation "quadtable" does not exist -LINE 1: select f1, (q).c1, (qq.q).c1.i from quadtable qq order by 1; - ^ + f1 | c1 | i +----+-----------+----- + 1 | (3.3,4.4) | 4.4 + 2 | (,4.4) | 4.4 +(2 rows) + create temp table people (fn fullname, bd date); -ERROR: type "fullname" does not exist -LINE 1: create temp table people (fn fullname, bd date); - ^ insert into people values ('(Joe,Blow)', '1984-01-10'); -ERROR: relation "people" does not exist -LINE 1: insert into people values ('(Joe,Blow)', '1984-01-10'); - ^ select * from people; -ERROR: relation "people" does not exist -LINE 1: select * from people; - ^ + fn | bd +------------+------------ + (Joe,Blow) | 01-10-1984 +(1 row) + -- at the moment this will not work due to ALTER TABLE inadequacy: alter table fullname add column suffix text default ''; -ERROR: relation "fullname" does not exist +ERROR: cannot alter table "fullname" because column "people"."fn" uses its rowtype -- but this should work: alter table fullname add column suffix text default null; -ERROR: relation "fullname" does not exist select * from people; -ERROR: relation "people" does not exist -LINE 1: select * from people; - ^ + fn | bd +-------------+------------ + (Joe,Blow,) | 01-10-1984 +(1 row) + -- test insertion/updating of subfields update people set fn.suffix = 'Jr'; -ERROR: relation "people" does not exist -LINE 1: update people set fn.suffix = 'Jr'; - ^ select * from people; -ERROR: relation "people" does not exist -LINE 1: select * from people; - ^ -insert into quadtable (f1, q.c1.r, q.c2.i) values(44,55,66); -ERROR: relation "quadtable" does not exist -LINE 1: insert into quadtable (f1, q.c1.r, q.c2.i) values(44,55,66); - ^ + fn | bd +---------------+------------ + (Joe,Blow,Jr) | 01-10-1984 +(1 row) + +-- PGXCTODO: This test case makes a server crash due to query deparsing in planner +-- insert into quadtable (f1, q.c1.r, q.c2.i) values(44,55,66); select * from quadtable order by f1, q; -ERROR: relation "quadtable" does not exist -LINE 1: select * from quadtable order by f1, q; - ^ + f1 | q +----+--------------------------- + 1 | ("(3.3,4.4)","(5.5,6.6)") + 2 | ("(,4.4)","(5.5,6.6)") +(2 rows) + -- The object here is to ensure that toasted references inside -- composite values don't cause problems. The large f1 value will -- be toasted inside pp, it must still work after being copied to people. create temp table pp (f1 text); -ERROR: PG-XC does not yet support temporary tables insert into pp values (repeat('abcdefghijkl', 100000)); -ERROR: relation "pp" does not exist -LINE 1: insert into pp values (repeat('abcdefghijkl', 100000)); - ^ insert into people select ('Jim', f1, null)::fullname, current_date from pp; -ERROR: relation "people" does not exist -LINE 1: insert into people select ('Jim', f1, null)::fullname, curre... - ^ select (fn).first, substr((fn).last, 1, 20), length((fn).last) from people order by 1, 2; -ERROR: relation "people" does not exist -LINE 1: ... substr((fn).last, 1, 20), length((fn).last) from people ord... - ^ + first | substr | length +-------+--------+-------- + Joe | Blow | 4 +(1 row) + -- Test row comparison semantics. Prior to PG 8.2 we did this in a totally -- non-spec-compliant way. select ROW(1,2) < ROW(1,3) as true; @@ -286,19 +288,13 @@ select row(1,1.1) = any (array[ row(7,7.7), row(1,1.0), row(0,0.0) ]); -- Check behavior with a non-comparable rowtype create type cantcompare as (p point, r float8); create temp table cc (f1 cantcompare); -ERROR: PG-XC does not yet support temporary tables insert into cc values('("(1,2)",3)'); -ERROR: relation "cc" does not exist -LINE 1: insert into cc values('("(1,2)",3)'); - ^ insert into cc values('("(4,5)",6)'); -ERROR: relation "cc" does not exist -LINE 1: insert into cc values('("(4,5)",6)'); - ^ select * from cc order by f1; -- fail, but should complain about cantcompare -ERROR: relation "cc" does not exist +ERROR: could not identify an ordering operator for type cantcompare LINE 1: select * from cc order by f1; - ^ + ^ +HINT: Use an explicit ordering operator or modify the query. -- -- Test case derived from bug #5716: check multiple uses of a rowtype result -- @@ -343,21 +339,24 @@ rollback; -- the latter is too prone to be invoked unintentionally. -- select cast (fullname as text) from fullname; -ERROR: relation "fullname" does not exist -LINE 1: select cast (fullname as text) from fullname; - ^ + fullname +---------- +(0 rows) + select fullname::text from fullname; -ERROR: relation "fullname" does not exist -LINE 1: select fullname::text from fullname; - ^ + fullname +---------- +(0 rows) + select text(fullname) from fullname; -- error -ERROR: relation "fullname" does not exist +ERROR: function text(fullname) does not exist LINE 1: select text(fullname) from fullname; - ^ + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. select fullname.text from fullname; -- error -ERROR: relation "fullname" does not exist +ERROR: column fullname.text does not exist LINE 1: select fullname.text from fullname; - ^ + ^ -- same, but RECORD instead of named composite type: select cast (row('Jim', 'Beam') as text); row diff --git a/src/test/regress/expected/select_1.out b/src/test/regress/expected/select_1.out index ea438e5846..6f4fbf5e6f 100644 --- a/src/test/regress/expected/select_1.out +++ b/src/test/regress/expected/select_1.out @@ -527,91 +527,218 @@ ORDER BY column1,column2; -- Test ORDER BY options -- CREATE TEMP TABLE foo (f1 int); -ERROR: PG-XC does not yet support temporary tables INSERT INTO foo VALUES (42),(3),(10),(7),(null),(null),(1); -ERROR: relation "foo" does not exist -LINE 1: INSERT INTO foo VALUES (42),(3),(10),(7),(null),(null),(1); - ^ SELECT * FROM foo ORDER BY f1; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1; - ^ + f1 +---- + 1 + 3 + 7 + 10 + 42 + + +(7 rows) + SELECT * FROM foo ORDER BY f1 ASC; -- same thing -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 ASC; - ^ + f1 +---- + 1 + 3 + 7 + 10 + 42 + + +(7 rows) + SELECT * FROM foo ORDER BY f1 NULLS FIRST; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 NULLS FIRST; - ^ + f1 +---- + + + 1 + 3 + 7 + 10 + 42 +(7 rows) + SELECT * FROM foo ORDER BY f1 DESC; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 DESC; - ^ + f1 +---- + + + 42 + 10 + 7 + 3 + 1 +(7 rows) + SELECT * FROM foo ORDER BY f1 DESC NULLS LAST; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 DESC NULLS LAST; - ^ + f1 +---- + 42 + 10 + 7 + 3 + 1 + + +(7 rows) + -- check if indexscans do the right things CREATE INDEX fooi ON foo (f1); -ERROR: relation "foo" does not exist SET enable_sort = false; SELECT * FROM foo ORDER BY f1; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1; - ^ + f1 +---- + 1 + 3 + 7 + 10 + 42 + + +(7 rows) + SELECT * FROM foo ORDER BY f1 NULLS FIRST; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 NULLS FIRST; - ^ + f1 +---- + + + 1 + 3 + 7 + 10 + 42 +(7 rows) + SELECT * FROM foo ORDER BY f1 DESC; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 DESC; - ^ + f1 +---- + + + 42 + 10 + 7 + 3 + 1 +(7 rows) + SELECT * FROM foo ORDER BY f1 DESC NULLS LAST; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 DESC NULLS LAST; - ^ + f1 +---- + 42 + 10 + 7 + 3 + 1 + + +(7 rows) + DROP INDEX fooi; -ERROR: index "fooi" does not exist CREATE INDEX fooi ON foo (f1 DESC); -ERROR: relation "foo" does not exist SELECT * FROM foo ORDER BY f1; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1; - ^ + f1 +---- + 1 + 3 + 7 + 10 + 42 + + +(7 rows) + SELECT * FROM foo ORDER BY f1 NULLS FIRST; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 NULLS FIRST; - ^ + f1 +---- + + + 1 + 3 + 7 + 10 + 42 +(7 rows) + SELECT * FROM foo ORDER BY f1 DESC; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 DESC; - ^ + f1 +---- + + + 42 + 10 + 7 + 3 + 1 +(7 rows) + SELECT * FROM foo ORDER BY f1 DESC NULLS LAST; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 DESC NULLS LAST; - ^ + f1 +---- + 42 + 10 + 7 + 3 + 1 + + +(7 rows) + DROP INDEX fooi; -ERROR: index "fooi" does not exist CREATE INDEX fooi ON foo (f1 DESC NULLS LAST); -ERROR: relation "foo" does not exist SELECT * FROM foo ORDER BY f1; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1; - ^ + f1 +---- + 1 + 3 + 7 + 10 + 42 + + +(7 rows) + SELECT * FROM foo ORDER BY f1 NULLS FIRST; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 NULLS FIRST; - ^ + f1 +---- + + + 1 + 3 + 7 + 10 + 42 +(7 rows) + SELECT * FROM foo ORDER BY f1 DESC; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 DESC; - ^ + f1 +---- + + + 42 + 10 + 7 + 3 + 1 +(7 rows) + SELECT * FROM foo ORDER BY f1 DESC NULLS LAST; -ERROR: relation "foo" does not exist -LINE 1: SELECT * FROM foo ORDER BY f1 DESC NULLS LAST; - ^ + f1 +---- + 42 + 10 + 7 + 3 + 1 + + +(7 rows) + -- -- Test some corner cases that have been known to confuse the planner -- diff --git a/src/test/regress/expected/select_distinct_on_1.out b/src/test/regress/expected/select_distinct_on_1.out index 0c01725248..9f951f79a5 100644 --- a/src/test/regress/expected/select_distinct_on_1.out +++ b/src/test/regress/expected/select_distinct_on_1.out @@ -25,6 +25,5 @@ select distinct on (1) floor(random()) as r, f1 from int4_tbl order by 1,2; r | f1 ---+------------- 0 | -2147483647 - 0 | -123456 -(2 rows) +(1 row) diff --git a/src/test/regress/expected/sequence_2.out b/src/test/regress/expected/sequence_2.out index a83f486cee..562747ae99 100644 --- a/src/test/regress/expected/sequence_2.out +++ b/src/test/regress/expected/sequence_2.out @@ -153,7 +153,7 @@ ERROR: Postgres-XC does not support SERIAL yet DETAIL: The feature is not currently supported -- Both drops should fail, but with different error messages: DROP SEQUENCE t1_f1_seq; -ERROR: relation "t1_f1_seq" does not exist +ERROR: sequence "t1_f1_seq" does not exist DROP SEQUENCE myseq2; -- This however will work: DROP SEQUENCE myseq3; @@ -161,10 +161,10 @@ DROP TABLE t1; ERROR: table "t1" does not exist -- Fails because no longer existent: DROP SEQUENCE t1_f1_seq; -ERROR: relation "t1_f1_seq" does not exist +ERROR: sequence "t1_f1_seq" does not exist -- Now OK: DROP SEQUENCE myseq2; -ERROR: relation "myseq2" does not exist +ERROR: sequence "myseq2" does not exist -- -- Alter sequence -- diff --git a/src/test/regress/expected/temp_1.out b/src/test/regress/expected/temp_1.out index ef48e27b4d..2e7f73581f 100644 --- a/src/test/regress/expected/temp_1.out +++ b/src/test/regress/expected/temp_1.out @@ -6,47 +6,42 @@ CREATE TABLE temptest(col int); CREATE INDEX i_temptest ON temptest(col); CREATE TEMP TABLE temptest(tcol int); -ERROR: PG-XC does not yet support temporary tables CREATE INDEX i_temptest ON temptest(tcol); -ERROR: column "tcol" does not exist SELECT * FROM temptest; - col ------ + tcol +------ (0 rows) DROP INDEX i_temptest; DROP TABLE temptest; SELECT * FROM temptest; -ERROR: relation "temptest" does not exist -LINE 1: SELECT * FROM temptest; - ^ + col +----- +(0 rows) + DROP INDEX i_temptest; -ERROR: index "i_temptest" does not exist DROP TABLE temptest; -ERROR: table "temptest" does not exist -- test temp table selects CREATE TABLE temptest(col int); INSERT INTO temptest VALUES (1); CREATE TEMP TABLE temptest(tcol float); -ERROR: PG-XC does not yet support temporary tables INSERT INTO temptest VALUES (2.1); SELECT * FROM temptest; + tcol +------ + 2.1 +(1 row) + +DROP TABLE temptest; +SELECT * FROM temptest; col ----- 1 - 2 -(2 rows) +(1 row) DROP TABLE temptest; -SELECT * FROM temptest; -ERROR: relation "temptest" does not exist -LINE 1: SELECT * FROM temptest; - ^ -DROP TABLE temptest; -ERROR: table "temptest" does not exist -- test temp table deletion CREATE TEMP TABLE temptest(col int); -ERROR: PG-XC does not yet support temporary tables \c SELECT * FROM temptest; ERROR: relation "temptest" does not exist @@ -54,23 +49,23 @@ LINE 1: SELECT * FROM temptest; ^ -- Test ON COMMIT DELETE ROWS CREATE TEMP TABLE temptest(col int) ON COMMIT DELETE ROWS; -ERROR: PG-XC does not yet support temporary tables BEGIN; INSERT INTO temptest VALUES (1); -ERROR: relation "temptest" does not exist -LINE 1: INSERT INTO temptest VALUES (1); - ^ INSERT INTO temptest VALUES (2); -ERROR: current transaction is aborted, commands ignored until end of transaction block SELECT * FROM temptest ORDER BY 1; -ERROR: current transaction is aborted, commands ignored until end of transaction block + col +----- + 1 + 2 +(2 rows) + COMMIT; SELECT * FROM temptest; -ERROR: relation "temptest" does not exist -LINE 1: SELECT * FROM temptest; - ^ + col +----- +(0 rows) + DROP TABLE temptest; -ERROR: table "temptest" does not exist BEGIN; CREATE TEMP TABLE temptest(col) ON COMMIT DELETE ROWS AS SELECT 1; ERROR: INTO clause not yet supported @@ -86,13 +81,15 @@ ERROR: table "temptest" does not exist -- Test ON COMMIT DROP BEGIN; CREATE TEMP TABLE temptest(col int) ON COMMIT DROP; -ERROR: PG-XC does not yet support temporary tables INSERT INTO temptest VALUES (1); -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO temptest VALUES (2); -ERROR: current transaction is aborted, commands ignored until end of transaction block SELECT * FROM temptest ORDER BY 1; -ERROR: current transaction is aborted, commands ignored until end of transaction block + col +----- + 1 + 2 +(2 rows) + COMMIT; SELECT * FROM temptest; ERROR: relation "temptest" does not exist @@ -116,34 +113,34 @@ ERROR: INTO clause not yet supported -- Test foreign keys BEGIN; CREATE TEMP TABLE temptest1(col int PRIMARY KEY); -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "temptest1_pkey" for table "temptest1" CREATE TEMP TABLE temptest2(col int REFERENCES temptest1) ON COMMIT DELETE ROWS; -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO temptest1 VALUES (1); -ERROR: current transaction is aborted, commands ignored until end of transaction block INSERT INTO temptest2 VALUES (1); -ERROR: current transaction is aborted, commands ignored until end of transaction block COMMIT; SELECT * FROM temptest1; -ERROR: relation "temptest1" does not exist -LINE 1: SELECT * FROM temptest1; - ^ + col +----- + 1 +(1 row) + SELECT * FROM temptest2; -ERROR: relation "temptest2" does not exist -LINE 1: SELECT * FROM temptest2; - ^ + col +----- +(0 rows) + BEGIN; CREATE TEMP TABLE temptest3(col int PRIMARY KEY) ON COMMIT DELETE ROWS; -ERROR: PG-XC does not yet support temporary tables +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "temptest3_pkey" for table "temptest3" CREATE TEMP TABLE temptest4(col int REFERENCES temptest3); -ERROR: current transaction is aborted, commands ignored until end of transaction block COMMIT; +ERROR: unsupported ON COMMIT and foreign key combination +DETAIL: Table "temptest4" references "temptest3", but they do not have the same ON COMMIT setting. -- Test manipulation of temp schema's placement in search path create table public.whereami (f1 text); insert into public.whereami values ('public'); create temp table whereami (f1 text); -ERROR: PG-XC does not yet support temporary tables insert into whereami values ('temp'); create function public.whoami() returns text as $$select 'public'::text$$ language sql; @@ -151,11 +148,10 @@ create function pg_temp.whoami() returns text as $$select 'temp'::text$$ language sql; -- default should have pg_temp implicitly first, but only for tables select * from whereami order by f1; - f1 --------- - public + f1 +------ temp -(2 rows) +(1 row) select whoami(); whoami @@ -166,11 +162,10 @@ select whoami(); -- can list temp first explicitly, but it still doesn't affect functions set search_path = pg_temp, public; select * from whereami order by f1; - f1 --------- - public + f1 +------ temp -(2 rows) +(1 row) select whoami(); whoami @@ -184,8 +179,7 @@ select * from whereami order by f1; f1 -------- public - temp -(2 rows) +(1 row) select whoami(); whoami diff --git a/src/test/regress/expected/transactions_1.out b/src/test/regress/expected/transactions_1.out index c30fa25a56..3cf5273814 100644 --- a/src/test/regress/expected/transactions_1.out +++ b/src/test/regress/expected/transactions_1.out @@ -43,7 +43,6 @@ SELECT * FROM aggtest order by a, b; -- Read-only tests CREATE TABLE writetest (a int); CREATE TEMPORARY TABLE temptest (a int); -ERROR: PG-XC does not yet support temporary tables BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE; -- ok SELECT * FROM writetest; -- ok @@ -123,21 +122,17 @@ SELECT * FROM writetest; -- ok (0 rows) DELETE FROM temptest; -- ok -ERROR: relation "temptest" does not exist -LINE 1: DELETE FROM temptest; - ^ UPDATE temptest SET a = 0 FROM writetest WHERE temptest.a = 1 AND writetest.a = temptest.a; -- ok -ERROR: relation "temptest" does not exist -LINE 1: UPDATE temptest SET a = 0 FROM writetest WHERE temptest.a = ... - ^ +ERROR: Partition column can't be updated in current version PREPARE test AS UPDATE writetest SET a = 0; -- ok ERROR: Partition column can't be updated in current version EXECUTE test; -- fail ERROR: prepared statement "test" does not exist SELECT * FROM writetest, temptest; -- ok -ERROR: relation "temptest" does not exist -LINE 1: SELECT * FROM writetest, temptest; - ^ + a | a +---+--- +(0 rows) + CREATE TABLE test AS SELECT * FROM writetest; -- fail ERROR: INTO clause not yet supported START TRANSACTION READ WRITE; diff --git a/src/test/regress/expected/xc_temp.out b/src/test/regress/expected/xc_temp.out new file mode 100644 index 0000000000..7fb6df7472 --- /dev/null +++ b/src/test/regress/expected/xc_temp.out @@ -0,0 +1,952 @@ +-- +-- XC_TEMP +-- +-- Create TEMPORARY and normal tables +CREATE TABLE table_rep (a int, b_rep char(1)) DISTRIBUTE BY REPLICATION; +CREATE TABLE table_hash (a int, b_hash char(1)) DISTRIBUTE BY HASH(a); +CREATE TABLE table_rb (a int, b_rb char(1)) DISTRIBUTE BY ROUND ROBIN; +CREATE TEMP TABLE temptable_rep (a int, b_tprep char(1)) DISTRIBUTE BY REPLICATION; +CREATE TEMP TABLE temptable_hash (a int, b_tphash char(1)) DISTRIBUTE BY HASH(a); +CREATE TEMP TABLE temptable_rb (a int, b_tprb char(1)) DISTRIBUTE BY ROUND ROBIN; +INSERT INTO table_rep VALUES (1, 'a'); +INSERT INTO table_rep VALUES (2, 'b'); +INSERT INTO table_rep VALUES (3, 'c'); +INSERT INTO table_rep VALUES (4, NULL); +INSERT INTO table_rep VALUES (NULL, 'e'); +INSERT INTO table_hash VALUES (1, 'a'); +INSERT INTO table_hash VALUES (2, 'b'); +INSERT INTO table_hash VALUES (3, 'c'); +INSERT INTO table_hash VALUES (4, NULL); +INSERT INTO table_hash VALUES (NULL, 'e'); +INSERT INTO table_rb VALUES (1, 'a'); +INSERT INTO table_rb VALUES (2, 'b'); +INSERT INTO table_rb VALUES (3, 'c'); +INSERT INTO table_rb VALUES (4, NULL); +INSERT INTO table_rb VALUES (NULL, 'e'); +INSERT INTO temptable_rep VALUES (1, 'A'); +INSERT INTO temptable_rep VALUES (2, NULL); +INSERT INTO temptable_rep VALUES (3, 'C'); +INSERT INTO temptable_rep VALUES (4, 'D'); +INSERT INTO temptable_rep VALUES (NULL, 'E'); +INSERT INTO temptable_hash VALUES (1, 'A'); +INSERT INTO temptable_hash VALUES (2, 'B'); +INSERT INTO temptable_hash VALUES (3, NULL); +INSERT INTO temptable_hash VALUES (4, 'D'); +INSERT INTO temptable_hash VALUES (NULL, 'E'); +INSERT INTO temptable_rb VALUES (1, 'A'); +INSERT INTO temptable_rb VALUES (2, 'B'); +INSERT INTO temptable_rb VALUES (3, 'C'); +INSERT INTO temptable_rb VALUES (4, NULL); +INSERT INTO temptable_rb VALUES (NULL, 'E'); +-- Check global joins on each table combination +SELECT * FROM table_hash, temptable_hash ORDER BY 1,2,3,4; + a | b_hash | a | b_tphash +---+--------+---+---------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | + 1 | a | 4 | D + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | B + 2 | b | 3 | + 2 | b | 4 | D + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | B + 3 | c | 3 | + 3 | c | 4 | D + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | B + 4 | | 3 | + 4 | | 4 | D + 4 | | | E + | e | 1 | A + | e | 2 | B + | e | 3 | + | e | 4 | D + | e | | E +(25 rows) + +SELECT * FROM table_hash, temptable_rep ORDER BY 1,2,3,4; + a | b_hash | a | b_tprep +---+--------+---+--------- + 1 | a | 1 | A + 1 | a | 2 | + 1 | a | 3 | C + 1 | a | 4 | D + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | + 2 | b | 3 | C + 2 | b | 4 | D + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | + 3 | c | 3 | C + 3 | c | 4 | D + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | + 4 | | 3 | C + 4 | | 4 | D + 4 | | | E + | e | 1 | A + | e | 2 | + | e | 3 | C + | e | 4 | D + | e | | E +(25 rows) + +SELECT * FROM table_hash, temptable_rb ORDER BY 1,2,3,4; + a | b_hash | a | b_tprb +---+--------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | B + 3 | c | 3 | C + 3 | c | 4 | + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | B + 4 | | 3 | C + 4 | | 4 | + 4 | | | E + | e | 1 | A + | e | 2 | B + | e | 3 | C + | e | 4 | + | e | | E +(25 rows) + +SELECT * FROM table_rep, temptable_rep ORDER BY 1,2,3,4; + a | b_rep | a | b_tprep +---+-------+---+--------- + 1 | a | 1 | A + 1 | a | 2 | + 1 | a | 3 | C + 1 | a | 4 | D + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | + 2 | b | 3 | C + 2 | b | 4 | D + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | + 3 | c | 3 | C + 3 | c | 4 | D + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | + 4 | | 3 | C + 4 | | 4 | D + 4 | | | E + | e | 1 | A + | e | 2 | + | e | 3 | C + | e | 4 | D + | e | | E +(25 rows) + +SELECT * FROM table_rep, temptable_rb ORDER BY 1,2,3,4; + a | b_rep | a | b_tprb +---+-------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | B + 3 | c | 3 | C + 3 | c | 4 | + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | B + 4 | | 3 | C + 4 | | 4 | + 4 | | | E + | e | 1 | A + | e | 2 | B + | e | 3 | C + | e | 4 | + | e | | E +(25 rows) + +SELECT * FROM table_rb, temptable_rb ORDER BY 1,2,3,4; + a | b_rb | a | b_tprb +---+------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | B + 3 | c | 3 | C + 3 | c | 4 | + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | B + 4 | | 3 | C + 4 | | 4 | + 4 | | | E + | e | 1 | A + | e | 2 | B + | e | 3 | C + | e | 4 | + | e | | E +(25 rows) + +-- Equi-joins +SELECT * FROM table_hash, temptable_hash WHERE table_hash.a = temptable_hash.a ORDER BY 1,2,3,4; + a | b_hash | a | b_tphash +---+--------+---+---------- + 1 | a | 1 | A + 2 | b | 2 | B + 3 | c | 3 | + 4 | | 4 | D +(4 rows) + +SELECT * FROM table_hash, temptable_rep WHERE table_hash.a = temptable_rep.a ORDER BY 1,2,3,4; + a | b_hash | a | b_tprep +---+--------+---+--------- + 1 | a | 1 | A + 2 | b | 2 | + 3 | c | 3 | C + 4 | | 4 | D +(4 rows) + +SELECT * FROM table_hash, temptable_rb WHERE table_hash.a = temptable_rb.a ORDER BY 1,2,3,4; + a | b_hash | a | b_tprb +---+--------+---+-------- + 1 | a | 1 | A + 2 | b | 2 | B + 3 | c | 3 | C + 4 | | 4 | +(4 rows) + +SELECT * FROM table_rep, temptable_rep WHERE table_rep.a = temptable_rep.a ORDER BY 1,2,3,4; + a | b_rep | a | b_tprep +---+-------+---+--------- + 1 | a | 1 | A + 2 | b | 2 | + 3 | c | 3 | C + 4 | | 4 | D +(4 rows) + +SELECT * FROM table_rep, temptable_rb WHERE table_rep.a = temptable_rb.a ORDER BY 1,2,3,4; + a | b_rep | a | b_tprb +---+-------+---+-------- + 1 | a | 1 | A + 2 | b | 2 | B + 3 | c | 3 | C + 4 | | 4 | +(4 rows) + +SELECT * FROM table_rb, temptable_rb WHERE table_rb.a = temptable_rb.a ORDER BY 1,2,3,4; + a | b_rb | a | b_tprb +---+------+---+-------- + 1 | a | 1 | A + 2 | b | 2 | B + 3 | c | 3 | C + 4 | | 4 | +(4 rows) + +-- Non equi-joins +SELECT * FROM table_hash JOIN temptable_hash ON (table_hash.a <= temptable_hash.a) ORDER BY 1,2,3,4; + a | b_hash | a | b_tphash +---+--------+---+---------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | + 1 | a | 4 | D + 2 | b | 2 | B + 2 | b | 3 | + 2 | b | 4 | D + 3 | c | 3 | + 3 | c | 4 | D + 4 | | 4 | D +(10 rows) + +SELECT * FROM table_hash JOIN temptable_rep ON (table_hash.a <= temptable_rep.a) ORDER BY 1,2,3,4; + a | b_hash | a | b_tprep +---+--------+---+--------- + 1 | a | 1 | A + 1 | a | 2 | + 1 | a | 3 | C + 1 | a | 4 | D + 2 | b | 2 | + 2 | b | 3 | C + 2 | b | 4 | D + 3 | c | 3 | C + 3 | c | 4 | D + 4 | | 4 | D +(10 rows) + +SELECT * FROM table_hash JOIN temptable_rb ON (table_hash.a <= temptable_rb.a) ORDER BY 1,2,3,4; + a | b_hash | a | b_tprb +---+--------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 3 | c | 3 | C + 3 | c | 4 | + 4 | | 4 | +(10 rows) + +SELECT * FROM table_rep JOIN temptable_rep ON (table_rep.a <= temptable_rep.a) ORDER BY 1,2,3,4; + a | b_rep | a | b_tprep +---+-------+---+--------- + 1 | a | 1 | A + 1 | a | 2 | + 1 | a | 3 | C + 1 | a | 4 | D + 2 | b | 2 | + 2 | b | 3 | C + 2 | b | 4 | D + 3 | c | 3 | C + 3 | c | 4 | D + 4 | | 4 | D +(10 rows) + +SELECT * FROM table_rep JOIN temptable_rb ON (table_rep.a <= temptable_rb.a) ORDER BY 1,2,3,4; + a | b_rep | a | b_tprb +---+-------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 3 | c | 3 | C + 3 | c | 4 | + 4 | | 4 | +(10 rows) + +SELECT * FROM table_rb JOIN temptable_rb ON (table_rb.a <= temptable_rb.a) ORDER BY 1,2,3,4; + a | b_rb | a | b_tprb +---+------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 3 | c | 3 | C + 3 | c | 4 | + 4 | | 4 | +(10 rows) + +-- More complicated joins +-- Hash and temp Hash +SELECT * FROM table_hash NATURAL JOIN temptable_hash ORDER BY 1,2,3; + a | b_hash | b_tphash +---+--------+---------- + 1 | a | A + 2 | b | B + 3 | c | + 4 | | D +(4 rows) + +SELECT * FROM table_hash CROSS JOIN temptable_hash ORDER BY 1,2,3,4; + a | b_hash | a | b_tphash +---+--------+---+---------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | + 1 | a | 4 | D + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | B + 2 | b | 3 | + 2 | b | 4 | D + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | B + 3 | c | 3 | + 3 | c | 4 | D + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | B + 4 | | 3 | + 4 | | 4 | D + 4 | | | E + | e | 1 | A + | e | 2 | B + | e | 3 | + | e | 4 | D + | e | | E +(25 rows) + +SELECT * FROM table_hash INNER JOIN temptable_hash USING (a) ORDER BY 1,2,3; + a | b_hash | b_tphash +---+--------+---------- + 1 | a | A + 2 | b | B + 3 | c | + 4 | | D +(4 rows) + +SELECT * FROM table_hash LEFT OUTER JOIN temptable_hash USING (a) ORDER BY 1,2,3; + a | b_hash | b_tphash +---+--------+---------- + 1 | a | A + 2 | b | B + 3 | c | + 4 | | D + | e | +(5 rows) + +SELECT * FROM table_hash RIGHT OUTER JOIN temptable_hash USING (a) ORDER BY 1,2,3; + a | b_hash | b_tphash +---+--------+---------- + 1 | a | A + 2 | b | B + 3 | c | + 4 | | D + | | E +(5 rows) + +SELECT * FROM table_hash FULL OUTER JOIN temptable_hash USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +SELECT * FROM table_hash LEFT JOIN temptable_hash USING (a) ORDER BY 1,2,3; + a | b_hash | b_tphash +---+--------+---------- + 1 | a | A + 2 | b | B + 3 | c | + 4 | | D + | e | +(5 rows) + +SELECT * FROM table_hash RIGHT JOIN temptable_hash USING (a) ORDER BY 1,2,3; + a | b_hash | b_tphash +---+--------+---------- + 1 | a | A + 2 | b | B + 3 | c | + 4 | | D + | | E +(5 rows) + +SELECT * FROM table_hash FULL JOIN temptable_hash USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +-- Hash and temp Replication +SELECT * FROM table_hash NATURAL JOIN temptable_rep ORDER BY 1,2,3; + a | b_hash | b_tprep +---+--------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D +(4 rows) + +SELECT * FROM table_hash CROSS JOIN temptable_rep ORDER BY 1,2,3,4; + a | b_hash | a | b_tprep +---+--------+---+--------- + 1 | a | 1 | A + 1 | a | 2 | + 1 | a | 3 | C + 1 | a | 4 | D + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | + 2 | b | 3 | C + 2 | b | 4 | D + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | + 3 | c | 3 | C + 3 | c | 4 | D + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | + 4 | | 3 | C + 4 | | 4 | D + 4 | | | E + | e | 1 | A + | e | 2 | + | e | 3 | C + | e | 4 | D + | e | | E +(25 rows) + +SELECT * FROM table_hash INNER JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprep +---+--------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D +(4 rows) + +SELECT * FROM table_hash LEFT OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprep +---+--------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D + | e | +(5 rows) + +SELECT * FROM table_hash RIGHT OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprep +---+--------+--------- + 1 | a | A + 1 | | A + 2 | b | + 2 | | + 3 | c | C + 3 | | C + 4 | | D + 4 | | D + | | E + | | E +(10 rows) + +SELECT * FROM table_hash FULL OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +SELECT * FROM table_hash LEFT JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprep +---+--------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D + | e | +(5 rows) + +SELECT * FROM table_hash RIGHT JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprep +---+--------+--------- + 1 | a | A + 1 | | A + 2 | b | + 2 | | + 3 | c | C + 3 | | C + 4 | | D + 4 | | D + | | E + | | E +(10 rows) + +SELECT * FROM table_hash FULL JOIN temptable_rep USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +-- Hash and temp Round Robin +SELECT * FROM table_hash NATURAL JOIN temptable_rb ORDER BY 1,2,3; + a | b_hash | b_tprb +---+--------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | +(4 rows) + +SELECT * FROM table_hash CROSS JOIN temptable_rb ORDER BY 1,2,3,4; + a | b_hash | a | b_tprb +---+--------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | B + 3 | c | 3 | C + 3 | c | 4 | + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | B + 4 | | 3 | C + 4 | | 4 | + 4 | | | E + | e | 1 | A + | e | 2 | B + | e | 3 | C + | e | 4 | + | e | | E +(25 rows) + +SELECT * FROM table_hash INNER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprb +---+--------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | +(4 rows) + +SELECT * FROM table_hash LEFT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprb +---+--------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | e | +(5 rows) + +SELECT * FROM table_hash RIGHT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprb +---+--------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | | E +(5 rows) + +SELECT * FROM table_hash FULL OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +SELECT * FROM table_hash LEFT JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprb +---+--------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | e | +(5 rows) + +SELECT * FROM table_hash RIGHT JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_hash | b_tprb +---+--------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | | E +(5 rows) + +SELECT * FROM table_hash FULL JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +-- Replication and temp Replication +SELECT * FROM table_rep NATURAL JOIN temptable_rep ORDER BY 1,2,3; + a | b_rep | b_tprep +---+-------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D +(4 rows) + +SELECT * FROM table_rep CROSS JOIN temptable_rep ORDER BY 1,2,3,4; + a | b_rep | a | b_tprep +---+-------+---+--------- + 1 | a | 1 | A + 1 | a | 2 | + 1 | a | 3 | C + 1 | a | 4 | D + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | + 2 | b | 3 | C + 2 | b | 4 | D + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | + 3 | c | 3 | C + 3 | c | 4 | D + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | + 4 | | 3 | C + 4 | | 4 | D + 4 | | | E + | e | 1 | A + | e | 2 | + | e | 3 | C + | e | 4 | D + | e | | E +(25 rows) + +SELECT * FROM table_rep INNER JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprep +---+-------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D +(4 rows) + +SELECT * FROM table_rep LEFT OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprep +---+-------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D + | e | +(5 rows) + +SELECT * FROM table_rep RIGHT OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprep +---+-------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D + | | E +(5 rows) + +SELECT * FROM table_rep FULL OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +SELECT * FROM table_rep LEFT JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprep +---+-------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D + | e | +(5 rows) + +SELECT * FROM table_rep RIGHT JOIN temptable_rep USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprep +---+-------+--------- + 1 | a | A + 2 | b | + 3 | c | C + 4 | | D + | | E +(5 rows) + +SELECT * FROM table_rep FULL JOIN temptable_rep USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +-- Replication and temp Round Robin +SELECT * FROM table_rep NATURAL JOIN temptable_rb ORDER BY 1,2,3; + a | b_rep | b_tprb +---+-------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | +(4 rows) + +SELECT * FROM table_rep CROSS JOIN temptable_rb ORDER BY 1,2,3,4; + a | b_rep | a | b_tprb +---+-------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | B + 3 | c | 3 | C + 3 | c | 4 | + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | B + 4 | | 3 | C + 4 | | 4 | + 4 | | | E + | e | 1 | A + | e | 2 | B + | e | 3 | C + | e | 4 | + | e | | E +(25 rows) + +SELECT * FROM table_rep INNER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprb +---+-------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | +(4 rows) + +SELECT * FROM table_rep LEFT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprb +---+-------+-------- + 1 | a | A + 1 | a | + 2 | b | B + 2 | b | + 3 | c | C + 3 | c | + 4 | | + 4 | | + | e | + | e | +(10 rows) + +SELECT * FROM table_rep RIGHT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprb +---+-------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | | E +(5 rows) + +SELECT * FROM table_rep FULL OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +SELECT * FROM table_rep LEFT JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprb +---+-------+-------- + 1 | a | A + 1 | a | + 2 | b | B + 2 | b | + 3 | c | C + 3 | c | + 4 | | + 4 | | + | e | + | e | +(10 rows) + +SELECT * FROM table_rep RIGHT JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rep | b_tprb +---+-------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | | E +(5 rows) + +SELECT * FROM table_rep FULL JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +-- Round Robin and temp Round Robin +SELECT * FROM table_rb NATURAL JOIN temptable_rb ORDER BY 1,2,3; + a | b_rb | b_tprb +---+------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | +(4 rows) + +SELECT * FROM table_rb CROSS JOIN temptable_rb ORDER BY 1,2,3,4; + a | b_rb | a | b_tprb +---+------+---+-------- + 1 | a | 1 | A + 1 | a | 2 | B + 1 | a | 3 | C + 1 | a | 4 | + 1 | a | | E + 2 | b | 1 | A + 2 | b | 2 | B + 2 | b | 3 | C + 2 | b | 4 | + 2 | b | | E + 3 | c | 1 | A + 3 | c | 2 | B + 3 | c | 3 | C + 3 | c | 4 | + 3 | c | | E + 4 | | 1 | A + 4 | | 2 | B + 4 | | 3 | C + 4 | | 4 | + 4 | | | E + | e | 1 | A + | e | 2 | B + | e | 3 | C + | e | 4 | + | e | | E +(25 rows) + +SELECT * FROM table_rb INNER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rb | b_tprb +---+------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | +(4 rows) + +SELECT * FROM table_rb LEFT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rb | b_tprb +---+------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | e | +(5 rows) + +SELECT * FROM table_rb RIGHT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rb | b_tprb +---+------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | | E +(5 rows) + +SELECT * FROM table_rb FULL OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +SELECT * FROM table_rb LEFT JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rb | b_tprb +---+------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | e | +(5 rows) + +SELECT * FROM table_rb RIGHT JOIN temptable_rb USING (a) ORDER BY 1,2,3; + a | b_rb | b_tprb +---+------+-------- + 1 | a | A + 2 | b | B + 3 | c | C + 4 | | + | | E +(5 rows) + +SELECT * FROM table_rb FULL JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +ERROR: FULL JOIN clause not yet supported +-- Check that DROP with TEMP and non-TEMP tables fails correctly +DROP TABLE temptable_rep,table_rep; +ERROR: DROP not supported for TEMP and non-TEMP objects +DETAIL: You should separate TEMP and non-TEMP objects +-- Clean up everything +DROP TABLE table_rep,table_hash,table_rb; diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 66d965dcab..084f2cbb24 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -132,4 +132,4 @@ test: stats test: xc_groupby test: xc_distkey test: xc_having - +test: xc_temp diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql index 6b9855c4a4..4200c977b6 100644 --- a/src/test/regress/sql/cluster.sql +++ b/src/test/regress/sql/cluster.sql @@ -194,7 +194,7 @@ SELECT * FROM clustertest ORDER BY 1; create temp table clstr_temp (col1 int primary key, col2 text); insert into clstr_temp values (2, 'two'), (1, 'one'); cluster clstr_temp using clstr_temp_pkey; -select * from clstr_temp; +select * from clstr_temp order by 1; drop table clstr_temp; -- clean up diff --git a/src/test/regress/sql/rowtypes.sql b/src/test/regress/sql/rowtypes.sql index a8b4d4dc39..236096da74 100644 --- a/src/test/regress/sql/rowtypes.sql +++ b/src/test/regress/sql/rowtypes.sql @@ -58,7 +58,8 @@ update people set fn.suffix = 'Jr'; select * from people; -insert into quadtable (f1, q.c1.r, q.c2.i) values(44,55,66); +-- PGXCTODO: This test case makes a server crash due to query deparsing in planner +-- insert into quadtable (f1, q.c1.r, q.c2.i) values(44,55,66); select * from quadtable order by f1, q; diff --git a/src/test/regress/sql/xc_temp.sql b/src/test/regress/sql/xc_temp.sql new file mode 100644 index 0000000000..bc657d9db2 --- /dev/null +++ b/src/test/regress/sql/xc_temp.sql @@ -0,0 +1,138 @@ +-- +-- XC_TEMP +-- + +-- Create TEMPORARY and normal tables +CREATE TABLE table_rep (a int, b_rep char(1)) DISTRIBUTE BY REPLICATION; +CREATE TABLE table_hash (a int, b_hash char(1)) DISTRIBUTE BY HASH(a); +CREATE TABLE table_rb (a int, b_rb char(1)) DISTRIBUTE BY ROUND ROBIN; +CREATE TEMP TABLE temptable_rep (a int, b_tprep char(1)) DISTRIBUTE BY REPLICATION; +CREATE TEMP TABLE temptable_hash (a int, b_tphash char(1)) DISTRIBUTE BY HASH(a); +CREATE TEMP TABLE temptable_rb (a int, b_tprb char(1)) DISTRIBUTE BY ROUND ROBIN; +INSERT INTO table_rep VALUES (1, 'a'); +INSERT INTO table_rep VALUES (2, 'b'); +INSERT INTO table_rep VALUES (3, 'c'); +INSERT INTO table_rep VALUES (4, NULL); +INSERT INTO table_rep VALUES (NULL, 'e'); +INSERT INTO table_hash VALUES (1, 'a'); +INSERT INTO table_hash VALUES (2, 'b'); +INSERT INTO table_hash VALUES (3, 'c'); +INSERT INTO table_hash VALUES (4, NULL); +INSERT INTO table_hash VALUES (NULL, 'e'); +INSERT INTO table_rb VALUES (1, 'a'); +INSERT INTO table_rb VALUES (2, 'b'); +INSERT INTO table_rb VALUES (3, 'c'); +INSERT INTO table_rb VALUES (4, NULL); +INSERT INTO table_rb VALUES (NULL, 'e'); +INSERT INTO temptable_rep VALUES (1, 'A'); +INSERT INTO temptable_rep VALUES (2, NULL); +INSERT INTO temptable_rep VALUES (3, 'C'); +INSERT INTO temptable_rep VALUES (4, 'D'); +INSERT INTO temptable_rep VALUES (NULL, 'E'); +INSERT INTO temptable_hash VALUES (1, 'A'); +INSERT INTO temptable_hash VALUES (2, 'B'); +INSERT INTO temptable_hash VALUES (3, NULL); +INSERT INTO temptable_hash VALUES (4, 'D'); +INSERT INTO temptable_hash VALUES (NULL, 'E'); +INSERT INTO temptable_rb VALUES (1, 'A'); +INSERT INTO temptable_rb VALUES (2, 'B'); +INSERT INTO temptable_rb VALUES (3, 'C'); +INSERT INTO temptable_rb VALUES (4, NULL); +INSERT INTO temptable_rb VALUES (NULL, 'E'); + +-- Check global joins on each table combination +SELECT * FROM table_hash, temptable_hash ORDER BY 1,2,3,4; +SELECT * FROM table_hash, temptable_rep ORDER BY 1,2,3,4; +SELECT * FROM table_hash, temptable_rb ORDER BY 1,2,3,4; +SELECT * FROM table_rep, temptable_rep ORDER BY 1,2,3,4; +SELECT * FROM table_rep, temptable_rb ORDER BY 1,2,3,4; +SELECT * FROM table_rb, temptable_rb ORDER BY 1,2,3,4; + +-- Equi-joins +SELECT * FROM table_hash, temptable_hash WHERE table_hash.a = temptable_hash.a ORDER BY 1,2,3,4; +SELECT * FROM table_hash, temptable_rep WHERE table_hash.a = temptable_rep.a ORDER BY 1,2,3,4; +SELECT * FROM table_hash, temptable_rb WHERE table_hash.a = temptable_rb.a ORDER BY 1,2,3,4; +SELECT * FROM table_rep, temptable_rep WHERE table_rep.a = temptable_rep.a ORDER BY 1,2,3,4; +SELECT * FROM table_rep, temptable_rb WHERE table_rep.a = temptable_rb.a ORDER BY 1,2,3,4; +SELECT * FROM table_rb, temptable_rb WHERE table_rb.a = temptable_rb.a ORDER BY 1,2,3,4; + +-- Non equi-joins +SELECT * FROM table_hash JOIN temptable_hash ON (table_hash.a <= temptable_hash.a) ORDER BY 1,2,3,4; +SELECT * FROM table_hash JOIN temptable_rep ON (table_hash.a <= temptable_rep.a) ORDER BY 1,2,3,4; +SELECT * FROM table_hash JOIN temptable_rb ON (table_hash.a <= temptable_rb.a) ORDER BY 1,2,3,4; +SELECT * FROM table_rep JOIN temptable_rep ON (table_rep.a <= temptable_rep.a) ORDER BY 1,2,3,4; +SELECT * FROM table_rep JOIN temptable_rb ON (table_rep.a <= temptable_rb.a) ORDER BY 1,2,3,4; +SELECT * FROM table_rb JOIN temptable_rb ON (table_rb.a <= temptable_rb.a) ORDER BY 1,2,3,4; + +-- More complicated joins +-- Hash and temp Hash +SELECT * FROM table_hash NATURAL JOIN temptable_hash ORDER BY 1,2,3; +SELECT * FROM table_hash CROSS JOIN temptable_hash ORDER BY 1,2,3,4; +SELECT * FROM table_hash INNER JOIN temptable_hash USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash LEFT OUTER JOIN temptable_hash USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash RIGHT OUTER JOIN temptable_hash USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash FULL OUTER JOIN temptable_hash USING (a) ORDER BY 1,2,3; --Fails for the time being +SELECT * FROM table_hash LEFT JOIN temptable_hash USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash RIGHT JOIN temptable_hash USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash FULL JOIN temptable_hash USING (a) ORDER BY 1,2,3; --Fails for the time being + +-- Hash and temp Replication +SELECT * FROM table_hash NATURAL JOIN temptable_rep ORDER BY 1,2,3; +SELECT * FROM table_hash CROSS JOIN temptable_rep ORDER BY 1,2,3,4; +SELECT * FROM table_hash INNER JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash LEFT OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash RIGHT OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash FULL OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; --Fails for the time being +SELECT * FROM table_hash LEFT JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash RIGHT JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash FULL JOIN temptable_rep USING (a) ORDER BY 1,2,3; --Fails for the time being + +-- Hash and temp Round Robin +SELECT * FROM table_hash NATURAL JOIN temptable_rb ORDER BY 1,2,3; +SELECT * FROM table_hash CROSS JOIN temptable_rb ORDER BY 1,2,3,4; +SELECT * FROM table_hash INNER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash LEFT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash RIGHT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash FULL OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +SELECT * FROM table_hash LEFT JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash RIGHT JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_hash FULL JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being + +-- Replication and temp Replication +SELECT * FROM table_rep NATURAL JOIN temptable_rep ORDER BY 1,2,3; +SELECT * FROM table_rep CROSS JOIN temptable_rep ORDER BY 1,2,3,4; +SELECT * FROM table_rep INNER JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep LEFT OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep RIGHT OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep FULL OUTER JOIN temptable_rep USING (a) ORDER BY 1,2,3; --Fails for the time being +SELECT * FROM table_rep LEFT JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep RIGHT JOIN temptable_rep USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep FULL JOIN temptable_rep USING (a) ORDER BY 1,2,3; --Fails for the time being + +-- Replication and temp Round Robin +SELECT * FROM table_rep NATURAL JOIN temptable_rb ORDER BY 1,2,3; +SELECT * FROM table_rep CROSS JOIN temptable_rb ORDER BY 1,2,3,4; +SELECT * FROM table_rep INNER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep LEFT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep RIGHT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep FULL OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +SELECT * FROM table_rep LEFT JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep RIGHT JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rep FULL JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being + +-- Round Robin and temp Round Robin +SELECT * FROM table_rb NATURAL JOIN temptable_rb ORDER BY 1,2,3; +SELECT * FROM table_rb CROSS JOIN temptable_rb ORDER BY 1,2,3,4; +SELECT * FROM table_rb INNER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rb LEFT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rb RIGHT OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rb FULL OUTER JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being +SELECT * FROM table_rb LEFT JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rb RIGHT JOIN temptable_rb USING (a) ORDER BY 1,2,3; +SELECT * FROM table_rb FULL JOIN temptable_rb USING (a) ORDER BY 1,2,3; --Fails for the time being + +-- Check that DROP with TEMP and non-TEMP tables fails correctly +DROP TABLE temptable_rep,table_rep; + +-- Clean up everything +DROP TABLE table_rep,table_hash,table_rb; |