diff options
| -rw-r--r-- | src/backend/catalog/dependency.c | 15 | ||||
| -rw-r--r-- | src/backend/commands/sequence.c | 109 | ||||
| -rw-r--r-- | src/backend/commands/tablecmds.c | 14 | ||||
| -rw-r--r-- | src/backend/pgxc/plan/planner.c | 4 | ||||
| -rw-r--r-- | src/backend/tcop/utility.c | 233 | ||||
| -rw-r--r-- | src/include/commands/sequence.h | 1 | ||||
| -rw-r--r-- | src/include/pgxc/planner.h | 3 | ||||
| -rw-r--r-- | src/test/regress/expected/drop_if_exists_1.out | 91 | ||||
| -rw-r--r-- | src/test/regress/expected/plancache_1.out | 5 | ||||
| -rw-r--r-- | src/test/regress/expected/sequence_2.out | 12 |
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 -- |
