diff options
| author | Michael P | 2011-07-27 06:37:09 +0000 |
|---|---|---|
| committer | Michael P | 2011-07-27 06:37:09 +0000 |
| commit | 1e04470efe097fdaa61ebdff858d7394537d6f9e (patch) | |
| tree | 00e26cbeae53383e1c5fe19e070a4bad2816be24 /src | |
| parent | 93d93ce4984b3868d80a6eb6b58e67abf99ce50f (diff) | |
Support for TEMPORARY sequences
A temporary sequence is created only on local Coordinator.
It doesn't need any interaction with GTM as it only lives during the
session session is up.
Sequence algorithm for nextval, currval and lastval has been changed in
accordance to temporary sequences.
Moreover, this commit cleans up a part of the code used by XC in utility.c
to have a more effective lookup on objects when looking for the node
types utility queries should be sent to.
COMMENTS are changed to be executed only on Coordinators.
Comments on temporary objects need some special handling but this is
not targetted yet.
Diffstat (limited to 'src')
| -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 -- |
