summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael P2011-08-05 02:07:38 +0000
committerMichael P2011-08-05 02:07:38 +0000
commit8a15033d7d7ae7cbe9a100ea88b8e18f033f0cb4 (patch)
tree0afa598503e7af6615149db94f0de8509bb3e7dc
parent87502bc809b852337e09f391317cbbc0cc35faf8 (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.
-rw-r--r--src/backend/access/transam/xact.c17
-rw-r--r--src/backend/commands/comment.c42
-rw-r--r--src/backend/commands/copy.c6
-rw-r--r--src/backend/commands/schemacmds.c3
-rw-r--r--src/backend/commands/tablecmds.c117
-rw-r--r--src/backend/optimizer/plan/createplan.c10
-rw-r--r--src/backend/pgxc/plan/planner.c46
-rw-r--r--src/backend/pgxc/pool/execRemote.c63
-rw-r--r--src/backend/pgxc/pool/poolmgr.c186
-rw-r--r--src/backend/tcop/utility.c557
-rw-r--r--src/include/commands/comment.h4
-rw-r--r--src/include/commands/tablecmds.h8
-rw-r--r--src/include/pgxc/execRemote.h2
-rw-r--r--src/include/pgxc/planner.h5
-rw-r--r--src/include/pgxc/poolmgr.h25
-rw-r--r--src/test/regress/expected/cluster_1.out18
-rw-r--r--src/test/regress/expected/combocid_1.out76
-rw-r--r--src/test/regress/expected/copy2_1.out83
-rw-r--r--src/test/regress/expected/domain_1.out49
-rw-r--r--src/test/regress/expected/foreign_key_1.out28
-rw-r--r--src/test/regress/expected/functional_deps_1.out30
-rw-r--r--src/test/regress/expected/guc_1.out12
-rw-r--r--src/test/regress/expected/polymorphism_1.out263
-rw-r--r--src/test/regress/expected/returning_1.out12
-rw-r--r--src/test/regress/expected/rowtypes_1.out181
-rw-r--r--src/test/regress/expected/select_1.out247
-rw-r--r--src/test/regress/expected/select_distinct_on_1.out3
-rw-r--r--src/test/regress/expected/sequence_2.out6
-rw-r--r--src/test/regress/expected/temp_1.out106
-rw-r--r--src/test/regress/expected/transactions_1.out15
-rw-r--r--src/test/regress/expected/xc_temp.out952
-rw-r--r--src/test/regress/serial_schedule2
-rw-r--r--src/test/regress/sql/cluster.sql2
-rw-r--r--src/test/regress/sql/rowtypes.sql3
-rw-r--r--src/test/regress/sql/xc_temp.sql138
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;