summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/catalog/dependency.c15
-rw-r--r--src/backend/commands/sequence.c109
-rw-r--r--src/backend/commands/tablecmds.c14
-rw-r--r--src/backend/pgxc/plan/planner.c4
-rw-r--r--src/backend/tcop/utility.c233
-rw-r--r--src/include/commands/sequence.h1
-rw-r--r--src/include/pgxc/planner.h3
-rw-r--r--src/test/regress/expected/drop_if_exists_1.out91
-rw-r--r--src/test/regress/expected/plancache_1.out5
-rw-r--r--src/test/regress/expected/sequence_2.out12
10 files changed, 369 insertions, 118 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index d2f6617049..e2e534a20b 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -375,9 +375,10 @@ doRename(const ObjectAddress *object, const char *oldname, const char *newname)
* has also to be renamed on GTM.
* An operation with GTM can just be done from a remote Coordinator.
*/
- if (relKind == RELKIND_SEQUENCE
- && IS_PGXC_COORDINATOR
- && !IsConnFromCoord())
+ if (relKind == RELKIND_SEQUENCE &&
+ IS_PGXC_COORDINATOR &&
+ !IsConnFromCoord() &&
+ IsTempSequence(object->objectId))
{
Relation relseq = relation_open(object->objectId, AccessShareLock);
char *seqname = GetGlobalSeqName(relseq, NULL, oldname);
@@ -1164,9 +1165,13 @@ doDeletion(const ObjectAddress *object)
#ifdef PGXC
/*
* Drop the sequence on GTM.
- * Sequence is dropped on GTM by a remote Coordinator only.
+ * Sequence is dropped on GTM by a remote Coordinator only
+ * for a non temporary sequence.
*/
- if (relKind == RELKIND_SEQUENCE && IS_PGXC_COORDINATOR && !IsConnFromCoord())
+ if (relKind == RELKIND_SEQUENCE &&
+ IS_PGXC_COORDINATOR &&
+ !IsConnFromCoord() &&
+ !IsTempSequence(object->objectId))
{
/*
* The sequence has already been removed from coordinator,
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 21c1ed6e11..d26b226514 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -153,15 +153,6 @@ DefineSequence(CreateSeqStmt *seq)
init_params(seq->options, true, &new, &owned_by);
#endif
-#ifdef PGXC
- if (seq->sequence->relpersistence != RELPERSISTENCE_PERMANENT &&
- seq->sequence->relpersistence != RELPERSISTENCE_UNLOGGED)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("Postgres-XC does not support TEMPORARY SEQUENCE yet"),
- errdetail("The feature is not currently supported")));
-#endif
-
/*
* Create relation (and fill value[] and null[] for the tuple)
*/
@@ -280,8 +271,14 @@ DefineSequence(CreateSeqStmt *seq)
heap_close(rel, NoLock);
#ifdef PGXC /* PGXC_COORD */
- /* Remote Coordinator is in charge of creating sequence in GTM */
- if (IS_PGXC_COORDINATOR && !IsConnFromCoord())
+ /*
+ * Remote Coordinator is in charge of creating sequence in GTM.
+ * If sequence is temporary, it is not necessary to create it on GTM.
+ */
+ if (IS_PGXC_COORDINATOR &&
+ !IsConnFromCoord() &&
+ (seq->sequence->relpersistence == RELPERSISTENCE_PERMANENT ||
+ seq->sequence->relpersistence == RELPERSISTENCE_UNLOGGED))
{
char *seqname = GetGlobalSeqName(rel, NULL, NULL);
@@ -585,8 +582,13 @@ AlterSequence(AlterSeqStmt *stmt)
relation_close(seqrel, NoLock);
#ifdef PGXC
- /* Remote Coordinator is in charge of create sequence in GTM */
- if (IS_PGXC_COORDINATOR && !IsConnFromCoord())
+ /*
+ * Remote Coordinator is in charge of create sequence in GTM
+ * If sequence is temporary, no need to go through GTM.
+ */
+ if (IS_PGXC_COORDINATOR &&
+ !IsConnFromCoord() &&
+ seqrel->rd_backend != MyBackendId)
{
char *seqname = GetGlobalSeqName(seqrel, NULL, NULL);
@@ -653,6 +655,9 @@ nextval_internal(Oid relid)
next,
rescnt = 0;
bool logit = false;
+#ifdef PGXC
+ bool is_temp;
+#endif
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
@@ -668,6 +673,10 @@ nextval_internal(Oid relid)
if (seqrel->rd_backend != MyBackendId)
PreventCommandIfReadOnly("nextval()");
+#ifdef PGXC
+ is_temp = seqrel->rd_backend == MyBackendId;
+#endif
+
if (elm->last != elm->cached) /* some numbers were cached */
{
Assert(elm->last_valid);
@@ -683,7 +692,7 @@ nextval_internal(Oid relid)
page = BufferGetPage(buf);
#ifdef PGXC /* PGXC_COORD */
- if (IS_PGXC_COORDINATOR)
+ if (IS_PGXC_COORDINATOR && !is_temp)
{
char *seqname = GetGlobalSeqName(seqrel, NULL, NULL);
@@ -763,7 +772,11 @@ nextval_internal(Oid relid)
* Check MAXVALUE for ascending sequences and MINVALUE for descending
* sequences
*/
-#ifndef PGXC
+#ifdef PGXC
+ /* Temporary sequences go through normal process */
+ if (is_temp)
+ {
+#endif
/* Result has been checked and received from GTM */
if (incby > 0)
{
@@ -811,13 +824,19 @@ nextval_internal(Oid relid)
else
next += incby;
}
+#ifdef PGXC
+ }
#endif
fetch--;
if (rescnt < cache)
{
log--;
rescnt++;
-#ifndef PGXC
+#ifdef PGXC
+ /* Temporary sequences can go through normal process */
+ if (is_temp)
+ {
+#endif
/*
* This part is not taken into account,
* result has been received from GTM
@@ -825,6 +844,8 @@ nextval_internal(Oid relid)
last = next;
if (rescnt == 1) /* if it's first result - */
result = next; /* it's what to return */
+#ifdef PGXC
+ }
#endif
}
}
@@ -832,7 +853,11 @@ nextval_internal(Oid relid)
log -= fetch; /* adjust for any unfetched numbers */
Assert(log >= 0);
-#ifndef PGXC
+#ifdef PGXC
+ /* Temporary sequences go through normal process */
+ if (is_temp)
+ {
+#endif
/* Result has been received from GTM */
/* save info in local cache */
elm->last = result; /* last returned number */
@@ -881,8 +906,13 @@ nextval_internal(Oid relid)
seq->log_cnt = log; /* how much is logged */
END_CRIT_SECTION();
-#else
- seq->log_cnt = log;
+
+#ifdef PGXC
+ }
+ else
+ {
+ seq->log_cnt = log;
+ }
#endif
UnlockReleaseBuffer(buf);
@@ -902,7 +932,6 @@ currval_oid(PG_FUNCTION_ARGS)
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
-
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK &&
pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
ereport(ERROR,
@@ -917,7 +946,8 @@ currval_oid(PG_FUNCTION_ARGS)
RelationGetRelationName(seqrel))));
#ifdef PGXC
- if (IS_PGXC_COORDINATOR)
+ if (IS_PGXC_COORDINATOR &&
+ seqrel->rd_backend != MyBackendId)
{
char *seqname = GetGlobalSeqName(seqrel, NULL, NULL);
@@ -928,8 +958,11 @@ currval_oid(PG_FUNCTION_ARGS)
errmsg("GTM error, could not obtain sequence value")));
pfree(seqname);
}
-#else
+ else {
+#endif
result = elm->last;
+#ifdef PGXC
+ }
#endif
relation_close(seqrel, NoLock);
@@ -991,6 +1024,9 @@ do_setval(Oid relid, int64 next, bool iscalled)
Relation seqrel;
Buffer buf;
Form_pg_sequence seq;
+#ifdef PGXC
+ bool is_temp;
+#endif
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
@@ -1005,6 +1041,10 @@ do_setval(Oid relid, int64 next, bool iscalled)
if (seqrel->rd_backend != MyBackendId)
PreventCommandIfReadOnly("setval()");
+#ifdef PGXC
+ is_temp = seqrel->rd_backend == MyBackendId;
+#endif
+
/* lock page' buffer and read tuple */
seq = read_info(elm, seqrel, &buf);
@@ -1025,7 +1065,7 @@ do_setval(Oid relid, int64 next, bool iscalled)
}
#ifdef PGXC
- if (IS_PGXC_COORDINATOR)
+ if (IS_PGXC_COORDINATOR && !is_temp)
{
char *seqname = GetGlobalSeqName(seqrel, NULL, NULL);
@@ -1571,11 +1611,12 @@ init_params(List *options, bool isInit,
#ifdef PGXC
/*
+ * GetGlobalSeqName
+ *
* Returns a global sequence name adapted to GTM
* Name format is dbname.schemaname.seqname
* so as to identify in a unique way in the whole cluster each sequence
*/
-
char *
GetGlobalSeqName(Relation seqrel, const char *new_seqname, const char *new_schemaname)
{
@@ -1614,6 +1655,26 @@ GetGlobalSeqName(Relation seqrel, const char *new_seqname, const char *new_schem
return seqname;
}
+
+/*
+ * IsTempSequence
+ *
+ * Determine if given sequence is temporary or not.
+ */
+bool
+IsTempSequence(Oid relid)
+{
+ Relation seqrel;
+ bool res;
+ SeqTable elm;
+
+ /* open and AccessShareLock sequence */
+ init_sequence(relid, &elm, &seqrel);
+
+ res = seqrel->rd_backend == MyBackendId;
+ relation_close(seqrel, NoLock);
+ return res;
+}
#endif
/*
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index dcd79b8ee3..644e572934 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -440,7 +440,9 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
* tables to appear in pg_temp at the front of its search path.
*/
#ifdef PGXC
- if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP && IsUnderPostmaster)
+ 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")));
@@ -2300,9 +2302,10 @@ RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
RenameRelationInternal(myrelid, newrelname, namespaceId);
#ifdef PGXC
/* Operation with GTM can only be done with a Remote Coordinator */
- if (IS_PGXC_COORDINATOR
- && !IsConnFromCoord()
- && (reltype == OBJECT_SEQUENCE || relkind == RELKIND_SEQUENCE)) /* It is possible to rename a sequence with ALTER TABLE */
+ if (IS_PGXC_COORDINATOR &&
+ !IsConnFromCoord() &&
+ (reltype == OBJECT_SEQUENCE || relkind == RELKIND_SEQUENCE) &&
+ !IsTempSequence(myrelid)) /* It is possible to rename a sequence with ALTER TABLE */
{
char *seqname = GetGlobalSeqName(targetrelation, NULL, NULL);
char *newseqname = GetGlobalSeqName(targetrelation, newrelname, NULL);
@@ -9081,7 +9084,8 @@ AlterTableNamespace(RangeVar *relation, const char *newschema,
/* Rename also sequence on GTM for a sequence */
if (IS_PGXC_COORDINATOR &&
!IsConnFromCoord() &&
- rel->rd_rel->relkind == RELKIND_SEQUENCE)
+ rel->rd_rel->relkind == RELKIND_SEQUENCE &&
+ !IsTempSequence(relid))
{
char *seqname = GetGlobalSeqName(rel, NULL, NULL);
char *newseqname = GetGlobalSeqName(rel, NULL, newschema);
diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c
index 54307387e4..7da7f848af 100644
--- a/src/backend/pgxc/plan/planner.c
+++ b/src/backend/pgxc/plan/planner.c
@@ -3188,6 +3188,10 @@ AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType rem
{
List *result = stmts;
+ /* If node is appplied on EXEC_ON_NONE, simply return the list unchanged */
+ if (remoteExecType == EXEC_ON_NONE)
+ return result;
+
/* Only a remote Coordinator is allowed to send a query to backend nodes */
if (IS_PGXC_COORDINATOR && !IsConnFromCoord())
{
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 1ebf7067e0..993c7cb859 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -71,6 +71,9 @@
static void ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes,
bool force_autocommit, RemoteQueryExecType exec_type);
+static RemoteQueryExecType ExecUtilityFindNodes(const char *queryString,
+ ObjectType objectType,
+ Oid relid);
#endif
@@ -793,6 +796,54 @@ standard_ProcessUtility(Node *parsetree,
case T_DropStmt:
{
DropStmt *stmt = (DropStmt *) parsetree;
+#ifdef PGXC
+ bool is_temp = false;
+
+ /*
+ * We need to check details of the objects being dropped and
+ * run command on correct nodes.
+ * This process has to be done before removing anything on local node
+ */
+ 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)
+ {
+ 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)
+ {
+ 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")));
+ }
+ }
+ }
+ }
+#endif
switch (stmt->removeType)
{
case OBJECT_TABLE:
@@ -845,12 +896,14 @@ standard_ProcessUtility(Node *parsetree,
(int) stmt->removeType);
break;
}
+
#ifdef PGXC
/*
- * We need to check details of the object being dropped and
- * run command on correct nodes
+ * 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())
+ if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && !is_temp)
{
/* Sequence and views exists only on Coordinators */
if (stmt->removeType == OBJECT_SEQUENCE ||
@@ -881,31 +934,12 @@ standard_ProcessUtility(Node *parsetree,
#ifdef PGXC
/*
- * We need to check details of the object being dropped and
- * run command on correct nodes
+ * PGXCTODO
+ * Comments on temporary objects need special handling
+ * depending on their types.
*/
if (IS_PGXC_COORDINATOR && !IsConnFromCoord())
- {
- CommentStmt *stmt = (CommentStmt *) parsetree;
-
- /* Sequence and views exists only on Coordinators */
- if (stmt->objtype == OBJECT_SEQUENCE ||
- stmt->objtype == OBJECT_VIEW)
- ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS);
- else if (stmt->objtype == OBJECT_RULE)
- {
- /*
- * Sometimes rules are created only on Coordinator (views), sometimes
- * on all nodes (other relations), so block it for the moment.
- */
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("Postgres-XC does not support COMMENT on RULE yet"),
- errdetail("The feature is not currently supported")));
- }
- else
- ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES);
- }
+ ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS);
#endif
break;
@@ -957,21 +991,21 @@ standard_ProcessUtility(Node *parsetree,
#ifdef PGXC
if (IS_PGXC_COORDINATOR && !IsConnFromCoord())
{
- RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES;
RenameStmt *stmt = (RenameStmt *) parsetree;
+ RemoteQueryExecType exec_type;
- if (stmt->renameType == OBJECT_SEQUENCE ||
- stmt->renameType == OBJECT_VIEW)
- remoteExecType = EXEC_ON_COORDS;
- else if (stmt->renameType == OBJECT_TABLE)
- {
- Oid relid = RangeVarGetRelid(stmt->relation, false);
-
- if (get_rel_relkind(relid) == RELKIND_SEQUENCE)
- remoteExecType = EXEC_ON_COORDS;
- }
+ /* Relation is not set for a schema */
+ if (stmt->relation)
+ exec_type = ExecUtilityFindNodes(queryString,
+ stmt->renameType,
+ RangeVarGetRelid(stmt->relation, false));
+ else
+ exec_type = EXEC_ON_ALL_NODES;
- ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType);
+ ExecUtilityStmtOnNodes(queryString,
+ NULL,
+ false,
+ exec_type);
}
#endif
ExecRenameStmt((RenameStmt *) parsetree);
@@ -981,20 +1015,20 @@ standard_ProcessUtility(Node *parsetree,
#ifdef PGXC
if (IS_PGXC_COORDINATOR && !IsConnFromCoord())
{
- RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES;
AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree;
- if (stmt->objectType == OBJECT_SEQUENCE ||
- stmt->objectType == OBJECT_VIEW)
- remoteExecType = EXEC_ON_COORDS;
- else if (stmt->objectType == OBJECT_TABLE)
- {
- Oid relid = RangeVarGetRelid(stmt->relation, false);
+ RemoteQueryExecType exec_type;
+ if (stmt->relation)
+ exec_type = ExecUtilityFindNodes(queryString,
+ stmt->objectType,
+ RangeVarGetRelid(stmt->relation, false));
+ else
+ exec_type = EXEC_ON_ALL_NODES;
- if (get_rel_relkind(relid) == RELKIND_SEQUENCE)
- remoteExecType = EXEC_ON_COORDS;
- }
- ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType);
+ ExecUtilityStmtOnNodes(queryString,
+ NULL,
+ false,
+ exec_type);
}
#endif
ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree);
@@ -1023,21 +1057,12 @@ standard_ProcessUtility(Node *parsetree,
*/
if (isTopLevel)
{
- RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES;
AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
+ RemoteQueryExecType exec_type = ExecUtilityFindNodes(queryString,
+ stmt->relkind,
+ RangeVarGetRelid(stmt->relation, false));
- if (stmt->relkind == OBJECT_VIEW ||
- stmt->relkind == OBJECT_SEQUENCE)
- remoteExecType = EXEC_ON_COORDS;
- else if (stmt->relkind == OBJECT_TABLE)
- {
- Oid relid = RangeVarGetRelid(stmt->relation, false);
-
- if (get_rel_relkind(relid) == RELKIND_SEQUENCE)
- remoteExecType = EXEC_ON_COORDS;
- }
-
- stmts = AddRemoteQueryNode(stmts, queryString, remoteExecType);
+ stmts = AddRemoteQueryNode(stmts, queryString, exec_type);
}
#endif
@@ -1125,10 +1150,9 @@ standard_ProcessUtility(Node *parsetree,
GrantStmt *stmt = (GrantStmt *) parsetree;
/* Launch GRANT on Coordinator if object is a sequence */
- if (stmt->objtype == ACL_OBJECT_SEQUENCE)
- remoteExecType = EXEC_ON_COORDS;
- else if (stmt->objtype == ACL_OBJECT_RELATION &&
- stmt->targtype == ACL_TARGET_OBJECT)
+ if ((stmt->objtype == ACL_OBJECT_RELATION &&
+ stmt->targtype == ACL_TARGET_OBJECT) ||
+ stmt->objtype == ACL_OBJECT_SEQUENCE)
{
/*
* In case object is a relation, differenciate the case
@@ -1146,9 +1170,18 @@ standard_ProcessUtility(Node *parsetree,
if (get_rel_relkind(relid) == RELKIND_SEQUENCE ||
get_rel_relkind(relid) == RELKIND_VIEW)
- remoteExecType = EXEC_ON_COORDS;
+ {
+ /* 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;
+ }
/* Check if objects can be launched at the same place as 1st one */
if (first)
@@ -1372,7 +1405,17 @@ standard_ProcessUtility(Node *parsetree,
DefineSequence((CreateSeqStmt *) parsetree);
#ifdef PGXC
if (IS_PGXC_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS);
+ {
+ /*
+ * If sequence is temporary, no need to send this query to other
+ * remote Coordinators.
+ */
+ CreateSeqStmt *stmt = (CreateSeqStmt *) parsetree;
+
+ if (stmt->sequence->relpersistence == RELPERSISTENCE_PERMANENT ||
+ stmt->sequence->relpersistence == RELPERSISTENCE_UNLOGGED)
+ ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS);
+ }
#endif
break;
@@ -1380,7 +1423,17 @@ standard_ProcessUtility(Node *parsetree,
AlterSequence((AlterSeqStmt *) parsetree);
#ifdef PGXC
if (IS_PGXC_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS);
+ {
+ /*
+ * If sequence is temporary, no need to send this query to other
+ * remote Coordinators.
+ */
+ AlterSeqStmt *stmt = (AlterSeqStmt *) parsetree;
+ Oid relid = RangeVarGetRelid(stmt->sequence, false);
+
+ if (!IsTempSequence(relid))
+ ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS);
+ }
#endif
break;
@@ -1936,6 +1989,10 @@ static void
ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes,
bool force_autocommit, RemoteQueryExecType exec_type)
{
+ /* Return if query is launched on no nodes */
+ if (exec_type == EXEC_ON_NONE)
+ return;
+
if (!IsConnFromCoord())
{
RemoteQuery *step = makeNode(RemoteQuery);
@@ -1949,6 +2006,44 @@ ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes,
pfree(step);
}
}
+
+/*
+ * ExecUtilityFindNodes
+ *
+ * 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.
+ */
+static RemoteQueryExecType
+ExecUtilityFindNodes(const char *queryString,
+ ObjectType object_type,
+ Oid relid)
+{
+ bool is_temp = false;
+ RemoteQueryExecType remoteExecType = EXEC_ON_NONE;
+
+ /* 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);
+
+ if (!is_temp)
+ {
+ remoteExecType = EXEC_ON_ALL_NODES;
+
+ 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;
+ }
+ }
+
+ return remoteExecType;
+}
#endif
/*
diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h
index ab9c54ea89..a31ef74e6b 100644
--- a/src/include/commands/sequence.h
+++ b/src/include/commands/sequence.h
@@ -82,6 +82,7 @@ extern void seq_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void seq_desc(StringInfo buf, uint8 xl_info, char *rec);
#ifdef PGXC
+extern bool IsTempSequence(Oid relid);
extern char *GetGlobalSeqName(Relation rel, const char *new_seqname, const char *new_schemaname);
#endif
diff --git a/src/include/pgxc/planner.h b/src/include/pgxc/planner.h
index 4228fbf3ee..04b3b148dc 100644
--- a/src/include/pgxc/planner.h
+++ b/src/include/pgxc/planner.h
@@ -65,7 +65,8 @@ typedef enum
{
EXEC_ON_DATANODES,
EXEC_ON_COORDS,
- EXEC_ON_ALL_NODES
+ EXEC_ON_ALL_NODES,
+ EXEC_ON_NONE
} RemoteQueryExecType;
typedef enum
diff --git a/src/test/regress/expected/drop_if_exists_1.out b/src/test/regress/expected/drop_if_exists_1.out
new file mode 100644
index 0000000000..93c0a555ef
--- /dev/null
+++ b/src/test/regress/expected/drop_if_exists_1.out
@@ -0,0 +1,91 @@
+--
+-- IF EXISTS tests
+--
+-- table (will be really dropped at the end)
+DROP TABLE test_exists;
+ERROR: table "test_exists" does not exist
+DROP TABLE IF EXISTS test_exists;
+NOTICE: table "test_exists" does not exist, skipping
+CREATE TABLE test_exists (a int, b text);
+-- view
+DROP VIEW test_view_exists;
+ERROR: view "test_view_exists" does not exist
+DROP VIEW IF EXISTS test_view_exists;
+NOTICE: view "test_view_exists" does not exist, skipping
+CREATE VIEW test_view_exists AS select * from test_exists;
+DROP VIEW IF EXISTS test_view_exists;
+DROP VIEW test_view_exists;
+ERROR: view "test_view_exists" does not exist
+-- index
+DROP INDEX test_index_exists;
+ERROR: index "test_index_exists" does not exist
+DROP INDEX IF EXISTS test_index_exists;
+NOTICE: index "test_index_exists" does not exist, skipping
+CREATE INDEX test_index_exists on test_exists(a);
+DROP INDEX IF EXISTS test_index_exists;
+DROP INDEX test_index_exists;
+ERROR: index "test_index_exists" does not exist
+-- sequence
+DROP SEQUENCE test_sequence_exists;
+ERROR: relation "test_sequence_exists" does not exist
+DROP SEQUENCE IF EXISTS test_sequence_exists;
+ERROR: relation "test_sequence_exists" does not exist
+CREATE SEQUENCE test_sequence_exists;
+DROP SEQUENCE IF EXISTS test_sequence_exists;
+DROP SEQUENCE test_sequence_exists;
+ERROR: relation "test_sequence_exists" does not exist
+-- schema
+DROP SCHEMA test_schema_exists;
+ERROR: schema "test_schema_exists" does not exist
+DROP SCHEMA IF EXISTS test_schema_exists;
+NOTICE: schema "test_schema_exists" does not exist, skipping
+CREATE SCHEMA test_schema_exists;
+DROP SCHEMA IF EXISTS test_schema_exists;
+DROP SCHEMA test_schema_exists;
+ERROR: schema "test_schema_exists" does not exist
+-- type
+DROP TYPE test_type_exists;
+ERROR: type "test_type_exists" does not exist
+DROP TYPE IF EXISTS test_type_exists;
+NOTICE: type "test_type_exists" does not exist, skipping
+CREATE type test_type_exists as (a int, b text);
+DROP TYPE IF EXISTS test_type_exists;
+DROP TYPE test_type_exists;
+ERROR: type "test_type_exists" does not exist
+-- domain
+DROP DOMAIN test_domain_exists;
+ERROR: type "test_domain_exists" does not exist
+DROP DOMAIN IF EXISTS test_domain_exists;
+NOTICE: type "test_domain_exists" does not exist, skipping
+CREATE domain test_domain_exists as int not null check (value > 0);
+DROP DOMAIN IF EXISTS test_domain_exists;
+DROP DOMAIN test_domain_exists;
+ERROR: type "test_domain_exists" does not exist
+-- drop the table
+DROP TABLE IF EXISTS test_exists;
+DROP TABLE test_exists;
+ERROR: table "test_exists" does not exist
+---
+--- role/user/group
+---
+CREATE USER tu1;
+CREATE ROLE tr1;
+CREATE GROUP tg1;
+DROP USER tu2;
+ERROR: role "tu2" does not exist
+DROP USER IF EXISTS tu1, tu2;
+NOTICE: role "tu2" does not exist, skipping
+DROP USER tu1;
+ERROR: role "tu1" does not exist
+DROP ROLE tr2;
+ERROR: role "tr2" does not exist
+DROP ROLE IF EXISTS tr1, tr2;
+NOTICE: role "tr2" does not exist, skipping
+DROP ROLE tr1;
+ERROR: role "tr1" does not exist
+DROP GROUP tg2;
+ERROR: role "tg2" does not exist
+DROP GROUP IF EXISTS tg1, tg2;
+NOTICE: role "tg2" does not exist, skipping
+DROP GROUP tg1;
+ERROR: role "tg1" does not exist
diff --git a/src/test/regress/expected/plancache_1.out b/src/test/regress/expected/plancache_1.out
index 8418572093..6ccf6abd35 100644
--- a/src/test/regress/expected/plancache_1.out
+++ b/src/test/regress/expected/plancache_1.out
@@ -169,8 +169,6 @@ NOTICE: drop cascades to table abc
reset search_path;
-- Check that invalidation deals with regclass constants
create temp sequence seq;
-ERROR: Postgres-XC does not support TEMPORARY SEQUENCE yet
-DETAIL: The feature is not currently supported
prepare p2 as select nextval('seq');
ERROR: Postgres-XC does not support PREPARE yet
DETAIL: The feature is not currently supported
@@ -178,10 +176,7 @@ execute p2;
ERROR: Postgres-XC does not support EXECUTE yet
DETAIL: The feature is not currently supported
drop sequence seq;
-ERROR: sequence "seq" does not exist
create temp sequence seq;
-ERROR: Postgres-XC does not support TEMPORARY SEQUENCE yet
-DETAIL: The feature is not currently supported
execute p2;
ERROR: Postgres-XC does not support EXECUTE yet
DETAIL: The feature is not currently supported
diff --git a/src/test/regress/expected/sequence_2.out b/src/test/regress/expected/sequence_2.out
index df9eadff47..a83f486cee 100644
--- a/src/test/regress/expected/sequence_2.out
+++ b/src/test/regress/expected/sequence_2.out
@@ -143,11 +143,7 @@ LINE 1: SELECT * FROM serialTest ORDER BY f1, f2;
-- Check dependencies of serial and ordinary sequences
--
CREATE TEMP SEQUENCE myseq2;
-ERROR: Postgres-XC does not support TEMPORARY SEQUENCE yet
-DETAIL: The feature is not currently supported
CREATE TEMP SEQUENCE myseq3;
-ERROR: Postgres-XC does not support TEMPORARY SEQUENCE yet
-DETAIL: The feature is not currently supported
CREATE TEMP TABLE t1 (
f1 serial,
f2 int DEFAULT nextval('myseq2'),
@@ -157,20 +153,18 @@ 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: sequence "t1_f1_seq" does not exist
+ERROR: relation "t1_f1_seq" does not exist
DROP SEQUENCE myseq2;
-ERROR: sequence "myseq2" does not exist
-- This however will work:
DROP SEQUENCE myseq3;
-ERROR: sequence "myseq3" does not exist
DROP TABLE t1;
ERROR: table "t1" does not exist
-- Fails because no longer existent:
DROP SEQUENCE t1_f1_seq;
-ERROR: sequence "t1_f1_seq" does not exist
+ERROR: relation "t1_f1_seq" does not exist
-- Now OK:
DROP SEQUENCE myseq2;
-ERROR: sequence "myseq2" does not exist
+ERROR: relation "myseq2" does not exist
--
-- Alter sequence
--