You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
(4) |
May
(28) |
Jun
(12) |
Jul
(11) |
Aug
(12) |
Sep
(5) |
Oct
(19) |
Nov
(14) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(18) |
Feb
(30) |
Mar
(115) |
Apr
(89) |
May
(50) |
Jun
(44) |
Jul
(22) |
Aug
(13) |
Sep
(11) |
Oct
(30) |
Nov
(28) |
Dec
(39) |
2012 |
Jan
(38) |
Feb
(18) |
Mar
(43) |
Apr
(91) |
May
(108) |
Jun
(46) |
Jul
(37) |
Aug
(44) |
Sep
(33) |
Oct
(29) |
Nov
(36) |
Dec
(15) |
2013 |
Jan
(35) |
Feb
(611) |
Mar
(5) |
Apr
(55) |
May
(30) |
Jun
(28) |
Jul
(458) |
Aug
(34) |
Sep
(9) |
Oct
(39) |
Nov
(22) |
Dec
(32) |
2014 |
Jan
(16) |
Feb
(16) |
Mar
(42) |
Apr
(179) |
May
(7) |
Jun
(6) |
Jul
(9) |
Aug
|
Sep
(4) |
Oct
|
Nov
(3) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
1
(2) |
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
(1) |
16
(3) |
17
|
18
|
19
|
20
|
21
|
22
|
23
|
24
(2) |
25
|
26
|
27
(1) |
28
(1) |
29
(1) |
30
(1) |
|
|
|
From: Pavan D. <pa...@us...> - 2010-06-24 08:16:32
|
Project "Postgres-XC". The branch, master has been updated via 75127cbf9ff834aabc4e4f39f2628f7a9646a6ea (commit) from c0169fa52ff019450c45dd9e50502e12375f33f2 (commit) - Log ----------------------------------------------------------------- commit 75127cbf9ff834aabc4e4f39f2628f7a9646a6ea Author: Pavan Deolasee <pav...@gm...> Date: Thu Jun 24 13:45:29 2010 +0530 Add a missing include file from the previous commit diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h index b5bb7d9..f54f74f 100644 --- a/src/include/commands/sequence.h +++ b/src/include/commands/sequence.h @@ -18,6 +18,9 @@ #include "access/xlog.h" #include "fmgr.h" +#ifdef PGXC +#include "utils/relcache.h" +#endif /* * On a machine with no 64-bit-int C datatype, sizeof(int64) will not be 8, ----------------------------------------------------------------------- Summary of changes: src/include/commands/sequence.h | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |
From: Pavan D. <pa...@us...> - 2010-06-24 07:33:34
|
Project "Postgres-XC". The branch, master has been updated via c0169fa52ff019450c45dd9e50502e12375f33f2 (commit) from a216b00661e2b76267681bade35a620566fe9345 (commit) - Log ----------------------------------------------------------------- commit c0169fa52ff019450c45dd9e50502e12375f33f2 Author: Pavan Deolasee <pav...@gm...> Date: Thu Jun 24 13:00:09 2010 +0530 Add support for ALTER Sequence. Michael Paquier with some editorilization from Pavan Deolasee diff --git a/src/backend/access/transam/gtm.c b/src/backend/access/transam/gtm.c index c3cb72b..f9499c9 100644 --- a/src/backend/access/transam/gtm.c +++ b/src/backend/access/transam/gtm.c @@ -172,10 +172,8 @@ GetSnapshotGTM(GlobalTransactionId gxid, bool canbe_grouped) } -/** +/* * Create a sequence on the GTM. - * - * */ int CreateSequenceGTM(char *seqname, GTM_Sequence increment, GTM_Sequence minval, @@ -189,7 +187,45 @@ CreateSequenceGTM(char *seqname, GTM_Sequence increment, GTM_Sequence minval, return conn ? open_sequence(conn, &seqkey, increment, minval, maxval, startval, cycle) : 0; } -/** +/* + * Alter a sequence on the GTM + */ +int +AlterSequenceGTM(char *seqname, GTM_Sequence increment, GTM_Sequence minval, + GTM_Sequence maxval, GTM_Sequence startval, GTM_Sequence lastval, bool cycle, bool is_restart) +{ + GTM_SequenceKeyData seqkey; + CheckConnection(); + seqkey.gsk_keylen = strlen(seqname); + seqkey.gsk_key = seqname; + + return conn ? alter_sequence(conn, &seqkey, increment, minval, maxval, startval, lastval, cycle, is_restart) : 0; +} + +/* + * get the current sequence value + */ + +GTM_Sequence +GetCurrentValGTM(char *seqname) +{ + GTM_Sequence ret = -1; + GTM_SequenceKeyData seqkey; + CheckConnection(); + seqkey.gsk_keylen = strlen(seqname); + seqkey.gsk_key = seqname; + + if (conn) + ret = get_current(conn, &seqkey); + if (ret < 0) + { + CloseGTM(); + InitGTM(); + } + return ret; +} + +/* * Get the next sequence value */ GTM_Sequence @@ -211,7 +247,21 @@ GetNextValGTM(char *seqname) return ret; } -/** +/* + * Set values for sequence + */ +int +SetValGTM(char *seqname, GTM_Sequence nextval, bool iscalled) +{ + GTM_SequenceKeyData seqkey; + CheckConnection(); + seqkey.gsk_keylen = strlen(seqname); + seqkey.gsk_key = seqname; + + return conn ? set_val(conn, &seqkey, nextval, iscalled) : -1; +} + +/* * Drop the sequence */ int @@ -224,3 +274,19 @@ DropSequenceGTM(char *seqname) return conn ? close_sequence(conn, &seqkey) : -1; } + +/* + * Rename the sequence + */ +int +RenameSequenceGTM(char *seqname, const char *newseqname) +{ + GTM_SequenceKeyData seqkey, newseqkey; + CheckConnection(); + seqkey.gsk_keylen = strlen(seqname); + seqkey.gsk_key = seqname; + newseqkey.gsk_keylen = strlen(newseqname); + newseqkey.gsk_key = (char *)newseqname; + + return conn ? rename_sequence(conn, &seqkey, &newseqkey) : -1; +} diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index ba9a932..ba30206 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -35,6 +35,7 @@ #include "utils/lsyscache.h" #include "utils/resowner.h" #include "utils/syscache.h" +#include "commands/dbcommands.h" #ifdef PGXC #include "pgxc/pgxc.h" @@ -97,8 +98,13 @@ static int64 nextval_internal(Oid relid); static Relation open_share_lock(SeqTable seq); static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel); static Form_pg_sequence read_info(SeqTable elm, Relation rel, Buffer *buf); +#ifdef PGXC +static void init_params(List *options, bool isInit, + Form_pg_sequence new, List **owned_by, bool *is_restart); +#else static void init_params(List *options, bool isInit, - Form_pg_sequence new, List **owned_by); + Form_pg_sequence new, List **owned_by); +#endif static void do_setval(Oid relid, int64 next, bool iscalled); static void process_owned_by(Relation seqrel, List *owned_by); @@ -130,10 +136,15 @@ DefineSequence(CreateSeqStmt *seq) GTM_Sequence max_value = InvalidSequenceValue; GTM_Sequence increment = 1; bool cycle = false; + bool is_restart; #endif /* Check and set all option values */ +#ifdef PGXC + init_params(seq->options, true, &new, &owned_by, &is_restart); +#else init_params(seq->options, true, &new, &owned_by); +#endif /* * Create relation (and fill value[] and null[] for the tuple) @@ -341,14 +352,20 @@ DefineSequence(CreateSeqStmt *seq) #ifdef PGXC /* PGXC_COORD */ if (IS_PGXC_COORDINATOR) { + char *seqname = GetGlobalSeqName(rel, NULL); + /* We also need to create it on the GTM */ - if (CreateSequenceGTM(name.data, increment, min_value, max_value, + if (CreateSequenceGTM(seqname, + increment, + min_value, + max_value, start_value, cycle) < 0) { ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("GTM error, could not create sequence"))); } + pfree(seqname); } #endif } @@ -392,6 +409,15 @@ AlterSequenceInternal(Oid relid, List *options) Form_pg_sequence seq; FormData_pg_sequence new; List *owned_by; +#ifdef PGXC + GTM_Sequence start_value; + GTM_Sequence last_value; + GTM_Sequence min_value; + GTM_Sequence max_value; + GTM_Sequence increment; + bool cycle; + bool is_restart; +#endif /* open and AccessShareLock sequence */ init_sequence(relid, &elm, &seqrel); @@ -404,7 +430,11 @@ AlterSequenceInternal(Oid relid, List *options) memcpy(&new, seq, sizeof(FormData_pg_sequence)); /* Check and set new values */ +#ifdef PGXC + init_params(options, false, &new, &owned_by, &is_restart); +#else init_params(options, false, &new, &owned_by); +#endif /* Clear local cache so that we don't think we have cached numbers */ /* Note that we do not change the currval() state */ @@ -413,6 +443,15 @@ AlterSequenceInternal(Oid relid, List *options) /* Now okay to update the on-disk tuple */ memcpy(seq, &new, sizeof(FormData_pg_sequence)); +#ifdef PGXC + increment = new.increment_by; + min_value = new.min_value; + max_value = new.max_value; + start_value = new.start_value; + last_value = new.last_value; + cycle = new.is_cycled; +#endif + START_CRIT_SECTION(); MarkBufferDirty(buf); @@ -451,6 +490,27 @@ AlterSequenceInternal(Oid relid, List *options) process_owned_by(seqrel, owned_by); relation_close(seqrel, NoLock); + +#ifdef PGXC + if (IS_PGXC_COORDINATOR) + { + char *seqname = GetGlobalSeqName(seqrel, NULL); + + /* We also need to create it on the GTM */ + if (AlterSequenceGTM(seqname, + increment, + min_value, + max_value, + start_value, + last_value, + cycle, + is_restart) < 0) + ereport(ERROR, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("GTM error, could not alter sequence"))); + pfree(seqname); + } +#endif } @@ -527,14 +587,22 @@ nextval_internal(Oid relid) #ifdef PGXC /* PGXC_COORD */ if (IS_PGXC_COORDINATOR) { - /* Above, we still use the page as a locking mechanism to handle - * concurrency + char *seqname = GetGlobalSeqName(seqrel, NULL); + + /* + * Above, we still use the page as a locking mechanism to handle + * concurrency */ - result = (int64) GetNextValGTM(RelationGetRelationName(seqrel)); + result = (int64) GetNextValGTM(seqname); if (result < 0) ereport(ERROR, - (errcode(ERRCODE_CONNECTION_FAILURE), - errmsg("GTM error, could not obtain sequence value"))); + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("GTM error, could not obtain sequence value"))); + pfree(seqname); + + /* Update the on-disk data */ + seq->last_value = result; /* last fetched number */ + seq->is_called = true; } else { #endif @@ -714,6 +782,22 @@ currval_oid(PG_FUNCTION_ARGS) /* open and AccessShareLock sequence */ init_sequence(relid, &elm, &seqrel); +#ifdef PGXC + if (IS_PGXC_COORDINATOR) + { + char *seqname = GetGlobalSeqName(seqrel, NULL); + + result = (int64) GetCurrentValGTM(seqname); + if (result < 0) + ereport(ERROR, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("GTM error, could not obtain sequence value"))); + pfree(seqname); + } + else + { +#endif + if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK && pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK) ereport(ERROR, @@ -729,6 +813,10 @@ currval_oid(PG_FUNCTION_ARGS) result = elm->last; +#ifdef PGXC + } +#endif + relation_close(seqrel, NoLock); PG_RETURN_INT64(result); @@ -820,6 +908,24 @@ do_setval(Oid relid, int64 next, bool iscalled) bufm, bufx))); } +#ifdef PGXC + if (IS_PGXC_COORDINATOR) + { + char *seqname = GetGlobalSeqName(seqrel, NULL); + + if (SetValGTM(seqname, next, iscalled) < 0) + ereport(ERROR, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("GTM error, could not obtain sequence value"))); + pfree(seqname); + /* Update the on-disk data */ + seq->last_value = next; /* last fetched number */ + seq->is_called = iscalled; + } + else + { +#endif + /* Set the currval() state only if iscalled = true */ if (iscalled) { @@ -872,6 +978,10 @@ do_setval(Oid relid, int64 next, bool iscalled) END_CRIT_SECTION(); +#ifdef PGXC + } +#endif + UnlockReleaseBuffer(buf); relation_close(seqrel, NoLock); @@ -1050,8 +1160,13 @@ read_info(SeqTable elm, Relation rel, Buffer *buf) * otherwise, do not change existing options that aren't explicitly overridden. */ static void +#ifdef PGXC +init_params(List *options, bool isInit, + Form_pg_sequence new, List **owned_by, bool *is_restart) +#else init_params(List *options, bool isInit, Form_pg_sequence new, List **owned_by) +#endif { DefElem *start_value = NULL; DefElem *restart_value = NULL; @@ -1062,6 +1177,10 @@ init_params(List *options, bool isInit, DefElem *is_cycled = NULL; ListCell *option; +#ifdef PGXC + *is_restart = false; +#endif + *owned_by = NIL; foreach(option, options) @@ -1227,8 +1346,8 @@ init_params(List *options, bool isInit, snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value); ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("START value (%s) cannot be greater than MAXVALUE (%s)", - bufs, bufm))); + errmsg("START value (%s) cannot be greater than MAXVALUE (%s)", + bufs, bufm))); } /* RESTART [WITH] */ @@ -1238,6 +1357,9 @@ init_params(List *options, bool isInit, new->last_value = defGetInt64(restart_value); else new->last_value = new->start_value; +#ifdef PGXC + *is_restart = true; +#endif new->is_called = false; new->log_cnt = 1; } @@ -1258,8 +1380,8 @@ init_params(List *options, bool isInit, snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value); ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("RESTART value (%s) cannot be less than MINVALUE (%s)", - bufs, bufm))); + errmsg("RESTART value (%s) cannot be less than MINVALUE (%s)", + bufs, bufm))); } if (new->last_value > new->max_value) { @@ -1270,8 +1392,8 @@ init_params(List *options, bool isInit, snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value); ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("RESTART value (%s) cannot be greater than MAXVALUE (%s)", - bufs, bufm))); + errmsg("RESTART value (%s) cannot be greater than MAXVALUE (%s)", + bufs, bufm))); } /* CACHE */ @@ -1293,6 +1415,49 @@ init_params(List *options, bool isInit, new->cache_value = 1; } +#ifdef PGXC +/* + * 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) +{ + char *seqname, *dbname, *schemaname, *relname; + int charlen; + + /* Get all the necessary relation names */ + dbname = get_database_name(seqrel->rd_node.dbNode); + schemaname = get_namespace_name(RelationGetNamespace(seqrel)); + + if (new_seqname) + relname = new_seqname; + else + relname = RelationGetRelationName(seqrel); + + /* Calculate the global name size including the dots and \0 */ + charlen = strlen(dbname) + strlen(schemaname) + strlen(relname) + 3; + seqname = (char *) palloc(charlen); + + /* Form a unique sequence name with schema and database name for GTM */ + snprintf(seqname, + charlen, + "%s.%s.%s", + dbname, + schemaname, + relname); + + if (dbname) + pfree(dbname); + if (schemaname) + pfree(schemaname); + + return seqname; +} +#endif + /* * Process an OWNED BY option for CREATE/ALTER SEQUENCE * diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index fa6456a..33782c4 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -768,14 +768,27 @@ RemoveRelations(DropStmt *drop) add_exact_object_address(&obj, objects); - #ifdef PGXC /* PGXC_COORD */ /* PGXCTODO: allow the ability to rollback dropping sequences. */ /* Drop the sequence */ if (IS_PGXC_COORDINATOR && classform->relkind == RELKIND_SEQUENCE) { - DropSequenceGTM(rel->relname); + Relation relseq; + char *seqname; + + /* + * A relation is opened to get the schema and database name as + * such data is not available before when dropping a function. + */ + relseq = relation_open(obj.objectId, AccessShareLock); + seqname = GetGlobalSeqName(relseq, NULL); + + DropSequenceGTM(seqname); + pfree(seqname); + + /* Then close the relation opened previously */ + relation_close(relseq, AccessShareLock); } #endif ReleaseSysCache(tuple); @@ -2103,6 +2116,20 @@ RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype) /* Do the work */ RenameRelationInternal(myrelid, newrelname, namespaceId); +#ifdef PGXC + if (IS_PGXC_COORDINATOR && + (reltype == OBJECT_SEQUENCE || relkind == RELKIND_SEQUENCE)) /* It is possible to rename a sequence with ALTER TABLE */ + { + char *seqname = GetGlobalSeqName(targetrelation, NULL); + char *newseqname = GetGlobalSeqName(targetrelation, newrelname); + + /* We also need to rename it on the GTM */ + if (RenameSequenceGTM(seqname, newseqname) < 0) + ereport(ERROR, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("GTM error, could not rename sequence"))); + } +#endif /* * Close rel, but keep exclusive lock! diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index 0d73fc9..0fb4a2b 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -1466,14 +1466,9 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) { query_plan->exec_loc_type = EXEC_ON_DATA_NODES; - /* - * If the nodelist is NULL, it is not safe for us to - * execute - */ - if (!query_step->exec_nodes && StrictStatementChecking) - ereport(ERROR, - (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), - (errmsg("Cannot safely execute statement in a single step.")))); + /* If node list is NULL, execute on coordinator */ + if (!query_step->exec_nodes) + query_plan->exec_loc_type = EXEC_ON_COORD; } } @@ -1517,19 +1512,10 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) break; /* Statements that we only want to execute on the Coordinator */ - case T_CreateSeqStmt: case T_VariableShowStmt: query_plan->exec_loc_type = EXEC_ON_COORD; break; - /* DROP */ - case T_DropStmt: - if (((DropStmt *) parsetree)->removeType == OBJECT_SEQUENCE) - query_plan->exec_loc_type = EXEC_ON_COORD; - else - query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; - break; - /* * Statements that need to run in autocommit mode, on Coordinator * and Data Nodes with suppressed implicit two phase commit. @@ -1542,51 +1528,7 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; query_plan->force_autocommit = true; break; - case T_AlterObjectSchemaStmt: - /* Sequences are just defined on coordinator */ - if (((AlterObjectSchemaStmt *) parsetree)->objectType == OBJECT_SEQUENCE) - query_plan->exec_loc_type = EXEC_ON_COORD; - else - query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; - break; - case T_AlterSeqStmt: - /* Alter sequence is not supported yet, it needs complementary interactions with GTM */ - ereport(ERROR, - (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), - (errmsg("This command is not yet supported")))); - break; - case T_AlterTableStmt: - /* - * ALTER SEQUENCE needs some interactions with GTM, - * this query is not supported yet. - */ - if (((AlterTableStmt *) parsetree)->relkind == OBJECT_SEQUENCE) - ereport(ERROR, - (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), - (errmsg("Cannot yet alter a sequence")))); - else - query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; - break; - case T_CommentStmt: - /* Sequences are only defined on coordinator */ - if (((CommentStmt *) parsetree)->objtype == OBJECT_SEQUENCE) - query_plan->exec_loc_type = EXEC_ON_COORD; - else - query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; - break; - case T_RenameStmt: - /* Sequences are only defined on coordinator */ - if (((RenameStmt *) parsetree)->renameType == OBJECT_SEQUENCE) - /* - * Renaming a sequence requires interactions with GTM - * what is not supported yet - */ - ereport(ERROR, - (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), - (errmsg("Sequence renaming not yet supported, you should drop it and created a new one")))); - else - query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; - break; + case T_DropPropertyStmt: /* * Triggers are not yet supported by PGXC @@ -1619,10 +1561,14 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) case T_AlterFdwStmt: case T_AlterForeignServerStmt: case T_AlterFunctionStmt: + case T_AlterObjectSchemaStmt: case T_AlterOpFamilyStmt: + case T_AlterSeqStmt: + case T_AlterTableStmt: /* Can also be used to rename a sequence */ case T_AlterTSConfigurationStmt: case T_AlterTSDictionaryStmt: - case T_ClosePortalStmt: /* In case CLOSE ALL is issued */ + case T_ClosePortalStmt: /* In case CLOSE ALL is issued */ + case T_CommentStmt: case T_CompositeTypeStmt: case T_ConstraintsSetStmt: case T_CreateCastStmt: @@ -1635,19 +1581,22 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) case T_CreateOpClassStmt: case T_CreateOpFamilyStmt: case T_CreatePLangStmt: + case T_CreateSeqStmt: case T_CreateSchemaStmt: - case T_DeallocateStmt: /* Allow for DEALLOCATE ALL */ + case T_DeallocateStmt: /* Allow for DEALLOCATE ALL */ case T_DiscardStmt: case T_DropCastStmt: case T_DropFdwStmt: case T_DropForeignServerStmt: case T_DropPLangStmt: + case T_DropStmt: case T_IndexStmt: case T_LockStmt: case T_ReindexStmt: case T_RemoveFuncStmt: case T_RemoveOpClassStmt: case T_RemoveOpFamilyStmt: + case T_RenameStmt: case T_TruncateStmt: case T_VariableSetStmt: case T_ViewStmt: @@ -1695,11 +1644,11 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) * data node will do */ case T_ExplainStmt: - if (((ExplainStmt *) parsetree)->analyze) + if (((ExplainStmt *) parsetree)->analyze) ereport(ERROR, (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), (errmsg("ANALYZE with EXPLAIN is currently not supported.")))); - + query_step->exec_nodes = palloc0(sizeof(Exec_Nodes)); query_step->exec_nodes->nodelist = GetAnyDataNode(); query_step->exec_nodes->baselocatortype = LOCATOR_TYPE_RROBIN; diff --git a/src/gtm/client/fe-protocol.c b/src/gtm/client/fe-protocol.c index a102202..051bb1d 100644 --- a/src/gtm/client/fe-protocol.c +++ b/src/gtm/client/fe-protocol.c @@ -493,12 +493,16 @@ gtmpqParseSuccess(GTM_Conn *conn, GTM_Result *result) case SEQUENCE_INIT_RESULT: case SEQUENCE_RESET_RESULT: case SEQUENCE_CLOSE_RESULT: + case SEQUENCE_RENAME_RESULT: + case SEQUENCE_ALTER_RESULT: + case SEQUENCE_SET_VAL_RESULT: if (gtmpqReadSeqKey(&result->gr_resdata.grd_seqkey, conn)) result->gr_status = -1; break; case SEQUENCE_GET_CURRENT_RESULT: case SEQUENCE_GET_NEXT_RESULT: + case SEQUENCE_GET_LAST_RESULT: if (gtmpqReadSeqKey(&result->gr_resdata.grd_seq.seqkey, conn)) { result->gr_status = -1; @@ -566,6 +570,9 @@ gtmpqFreeResultData(GTM_Result *result, bool is_proxy) case SEQUENCE_INIT_RESULT: case SEQUENCE_RESET_RESULT: case SEQUENCE_CLOSE_RESULT: + case SEQUENCE_RENAME_RESULT: + case SEQUENCE_ALTER_RESULT: + case SEQUENCE_SET_VAL_RESULT: if (result->gr_resdata.grd_seqkey.gsk_key != NULL) free(result->gr_resdata.grd_seqkey.gsk_key); result->gr_resdata.grd_seqkey.gsk_key = NULL; @@ -573,6 +580,7 @@ gtmpqFreeResultData(GTM_Result *result, bool is_proxy) case SEQUENCE_GET_CURRENT_RESULT: case SEQUENCE_GET_NEXT_RESULT: + case SEQUENCE_GET_LAST_RESULT: if (result->gr_resdata.grd_seq.seqkey.gsk_key != NULL) free(result->gr_resdata.grd_seq.seqkey.gsk_key); result->gr_resdata.grd_seqkey.gsk_key = NULL; diff --git a/src/gtm/client/gtm_client.c b/src/gtm/client/gtm_client.c index 089689e..9df28c7 100644 --- a/src/gtm/client/gtm_client.c +++ b/src/gtm/client/gtm_client.c @@ -356,6 +356,51 @@ send_failed: } int +alter_sequence(GTM_Conn *conn, GTM_SequenceKey key, GTM_Sequence increment, + GTM_Sequence minval, GTM_Sequence maxval, + GTM_Sequence startval, GTM_Sequence lastval, bool cycle, bool is_restart) +{ + GTM_Result *res = NULL; + time_t finish_time; + + /* Start the message. */ + if (gtmpqPutMsgStart('C', true, conn) || + gtmpqPutInt(MSG_SEQUENCE_ALTER, sizeof (GTM_MessageType), conn) || + gtmpqPutInt(key->gsk_keylen, 4, conn) || + gtmpqPutnchar(key->gsk_key, key->gsk_keylen, conn) || + gtmpqPutnchar((char *)&increment, sizeof (GTM_Sequence), conn) || + gtmpqPutnchar((char *)&minval, sizeof (GTM_Sequence), conn) || + gtmpqPutnchar((char *)&maxval, sizeof (GTM_Sequence), conn) || + gtmpqPutnchar((char *)&startval, sizeof (GTM_Sequence), conn) || + gtmpqPutnchar((char *)&lastval, sizeof (GTM_Sequence), conn) || + gtmpqPutc(cycle, conn) || + gtmpqPutc(is_restart, conn)) + goto send_failed; + + /* Finish the message. */ + if (gtmpqPutMsgEnd(conn)) + goto send_failed; + + /* Flush to ensure backend gets it. */ + if (gtmpqFlush(conn)) + goto send_failed; + + finish_time = time(NULL) + CLIENT_GTM_TIMEOUT; + if (gtmpqWaitTimed(true, false, conn, finish_time) || + gtmpqReadData(conn) < 0) + goto receive_failed; + + if ((res = GTMPQgetResult(conn)) == NULL) + goto receive_failed; + + return res->gr_status; + +receive_failed: +send_failed: + return -1; +} + +int close_sequence(GTM_Conn *conn, GTM_SequenceKey key) { GTM_Result *res = NULL; @@ -391,6 +436,44 @@ send_failed: return -1; } +int +rename_sequence(GTM_Conn *conn, GTM_SequenceKey key, GTM_SequenceKey newkey) +{ + GTM_Result *res = NULL; + time_t finish_time; + + /* Start the message. */ + if (gtmpqPutMsgStart('C', true, conn) || + gtmpqPutInt(MSG_SEQUENCE_RENAME, sizeof (GTM_MessageType), conn) || + gtmpqPutInt(key->gsk_keylen, 4, conn) || + gtmpqPutnchar(key->gsk_key, key->gsk_keylen, conn)|| + gtmpqPutInt(newkey->gsk_keylen, 4, conn) || + gtmpqPutnchar(newkey->gsk_key, newkey->gsk_keylen, conn)) + goto send_failed; + + /* Finish the message. */ + if (gtmpqPutMsgEnd(conn)) + goto send_failed; + + /* Flush to ensure backend gets it. */ + if (gtmpqFlush(conn)) + goto send_failed; + + finish_time = time(NULL) + CLIENT_GTM_TIMEOUT; + if (gtmpqWaitTimed(true, false, conn, finish_time) || + gtmpqReadData(conn) < 0) + goto receive_failed; + + if ((res = GTMPQgetResult(conn)) == NULL) + goto receive_failed; + + return res->gr_status; + + receive_failed: + send_failed: + return -1; +} + GTM_Sequence get_current(GTM_Conn *conn, GTM_SequenceKey key) { @@ -430,13 +513,51 @@ send_failed: return -1; } +int +set_val(GTM_Conn *conn, GTM_SequenceKey key, GTM_Sequence nextval, bool iscalled) +{ + GTM_Result *res = NULL; + time_t finish_time; + + /* Start the message. */ + if (gtmpqPutMsgStart('C', true, conn) || + gtmpqPutInt(MSG_SEQUENCE_SET_VAL, sizeof (GTM_MessageType), conn) || + gtmpqPutInt(key->gsk_keylen, 4, conn) || + gtmpqPutnchar(key->gsk_key, key->gsk_keylen, conn) || + gtmpqPutnchar((char *)&nextval, sizeof (GTM_Sequence), conn) || + gtmpqPutc(iscalled, conn)) + goto send_failed; + + /* Finish the message. */ + if (gtmpqPutMsgEnd(conn)) + goto send_failed; + + /* Flush to ensure backend gets it. */ + if (gtmpqFlush(conn)) + goto send_failed; + + finish_time = time(NULL) + CLIENT_GTM_TIMEOUT; + if (gtmpqWaitTimed(true, false, conn, finish_time) || + gtmpqReadData(conn) < 0) + goto receive_failed; + + if ((res = GTMPQgetResult(conn)) == NULL) + goto receive_failed; + + return res->gr_status; + +receive_failed: +send_failed: + return -1; +} + GTM_Sequence get_next(GTM_Conn *conn, GTM_SequenceKey key) { GTM_Result *res = NULL; time_t finish_time; - /* Start the message. */ + /* Start the message. */ if (gtmpqPutMsgStart('C', true, conn) || gtmpqPutInt(MSG_SEQUENCE_GET_NEXT, sizeof (GTM_MessageType), conn) || gtmpqPutInt(key->gsk_keylen, 4, conn) || diff --git a/src/gtm/main/gtm_seq.c b/src/gtm/main/gtm_seq.c index 73af34e..8611f40 100644 --- a/src/gtm/main/gtm_seq.c +++ b/src/gtm/main/gtm_seq.c @@ -326,9 +326,12 @@ GTM_SeqOpen(GTM_SequenceKey seqkey, */ seqinfo->gs_cycle = cycle; + /* Set the last value in case of a future restart */ + seqinfo->gs_last_value = seqinfo->gs_init_value; + if ((errcode = seq_add_seqinfo(seqinfo))) { - GTM_RWLockDestroy(&seqinfo->gs_lock); + GTM_RWLockDestroy(&seqinfo->gs_lock); pfree(seqinfo->gs_key); pfree(seqinfo); } @@ -336,6 +339,62 @@ GTM_SeqOpen(GTM_SequenceKey seqkey, } /* + * Alter a sequence + */ +int GTM_SeqAlter(GTM_SequenceKey seqkey, + GTM_Sequence increment_by, + GTM_Sequence minval, + GTM_Sequence maxval, + GTM_Sequence startval, + GTM_Sequence lastval, + bool cycle, + bool is_restart) +{ + GTM_SeqInfo *seqinfo = seq_find_seqinfo(seqkey); + + if (seqinfo == NULL) + { + ereport(LOG, + (EINVAL, + errmsg("The sequence with the given key does not exist"))); + return EINVAL; + } + + GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); + + /* Modify the data if necessary */ + + if (seqinfo->gs_cycle != cycle) + seqinfo->gs_cycle = cycle; + if (seqinfo->gs_min_value != minval) + seqinfo->gs_min_value = minval; + if (seqinfo->gs_max_value != maxval) + seqinfo->gs_max_value = maxval; + if (seqinfo->gs_increment_by != increment_by) + seqinfo->gs_increment_by = increment_by; + + /* Here Restart has been used with a value, reinitialize last_value to a new value */ + if (seqinfo->gs_last_value != lastval) + seqinfo->gs_last_value = lastval; + + /* Start has been used, reinitialize init value */ + if (seqinfo->gs_init_value != startval) + seqinfo->gs_last_value = seqinfo->gs_init_value = startval; + + /* Restart command has been used, reset the sequence */ + if (is_restart) + { + seqinfo->gs_called = false; + seqinfo->gs_init_value = seqinfo->gs_last_value; + } + + /* Remove the old key with the old name */ + GTM_RWLockRelease(&seqinfo->gs_lock); + seq_release_seqinfo(seqinfo); + return 0; +} + +/* * Restore a sequence. */ static int @@ -367,7 +426,7 @@ GTM_SeqRestore(GTM_SequenceKey seqkey, seqinfo->gs_min_value = minval; seqinfo->gs_max_value = maxval; - seqinfo->gs_init_value = startval; + seqinfo->gs_init_value = seqinfo->gs_last_value = startval; seqinfo->gs_value = curval; /* @@ -402,6 +461,66 @@ GTM_SeqClose(GTM_SequenceKey seqkey) } /* + * Rename an existing sequence with a new name + */ +int +GTM_SeqRename(GTM_SequenceKey seqkey, GTM_SequenceKey newseqkey) +{ + GTM_SeqInfo *seqinfo = seq_find_seqinfo(seqkey); + GTM_SeqInfo *newseqinfo = NULL; + int errcode = 0; + + /* replace old key by new key */ + if (seqinfo == NULL) + { + ereport(LOG, + (EINVAL, + errmsg("The sequence with the given key does not exist"))); + return EINVAL; + } + + /* Now create the new sequence info */ + newseqinfo = (GTM_SeqInfo *) palloc(sizeof (GTM_SeqInfo)); + + GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); + GTM_RWLockInit(&newseqinfo->gs_lock); + + newseqinfo->gs_ref_count = 0; + newseqinfo->gs_key = seq_copy_key(newseqkey); + newseqinfo->gs_state = seqinfo->gs_state; + newseqinfo->gs_called = seqinfo->gs_called; + + newseqinfo->gs_increment_by = seqinfo->gs_increment_by; + newseqinfo->gs_min_value = seqinfo->gs_min_value; + newseqinfo->gs_max_value = seqinfo->gs_max_value; + + newseqinfo->gs_init_value = seqinfo->gs_init_value; + newseqinfo->gs_value = seqinfo->gs_value; + newseqinfo->gs_cycle = seqinfo->gs_cycle; + + newseqinfo->gs_state = seqinfo->gs_state; + newseqinfo->gs_last_value = seqinfo->gs_last_value; + + /* Add the copy to the list */ + if ((errcode = seq_add_seqinfo(newseqinfo))) /* a lock is taken here for the new sequence */ + { + GTM_RWLockDestroy(&newseqinfo->gs_lock); + pfree(newseqinfo->gs_key); + pfree(newseqinfo); + return errcode; + } + + /* Remove the old key with the old name */ + GTM_RWLockRelease(&seqinfo->gs_lock); + /* Release first the structure as it has been taken previously */ + seq_release_seqinfo(seqinfo); + + /* Then close properly the old sequence */ + GTM_SeqClose(seqkey); + return errcode; +} + +/* * Get current value for the sequence without incrementing it */ GTM_Sequence @@ -436,7 +555,37 @@ GTM_SeqGetCurrent(GTM_SequenceKey seqkey) } /* - * Get next vlaue for the sequence + * Set values for the sequence + */ +int +GTM_SeqSetVal(GTM_SequenceKey seqkey, GTM_Sequence nextval, bool iscalled) +{ + GTM_SeqInfo *seqinfo = seq_find_seqinfo(seqkey); + + if (seqinfo == NULL) + { + ereport(LOG, + (EINVAL, + errmsg("The sequence with the given key does not exist"))); + return EINVAL; + } + + GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); + + if (seqinfo->gs_value != nextval) + seqinfo->gs_value = nextval; + if (seqinfo->gs_called != iscalled) + seqinfo->gs_called = iscalled; + + /* Remove the old key with the old name */ + GTM_RWLockRelease(&seqinfo->gs_lock); + seq_release_seqinfo(seqinfo); + + return 0; +} + +/* + * Get next value for the sequence */ GTM_Sequence GTM_SeqGetNext(GTM_SequenceKey seqkey) @@ -625,6 +774,75 @@ ProcessSequenceInitCommand(Port *myport, StringInfo message) } /* + * Process MSG_SEQUENCE_ALTER message + */ +void +ProcessSequenceAlterCommand(Port *myport, StringInfo message) +{ + GTM_SequenceKeyData seqkey; + GTM_Sequence increment, minval, maxval, startval, lastval; + bool cycle, is_restart; + StringInfoData buf; + int errcode; + MemoryContext oldContext; + + /* + * Get the sequence key + */ + seqkey.gsk_keylen = pq_getmsgint(message, sizeof (seqkey.gsk_keylen)); + seqkey.gsk_key = (char *)pq_getmsgbytes(message, seqkey.gsk_keylen); + + /* + * Read various sequence parameters + */ + memcpy(&increment, pq_getmsgbytes(message, sizeof (GTM_Sequence)), + sizeof (GTM_Sequence)); + memcpy(&minval, pq_getmsgbytes(message, sizeof (GTM_Sequence)), + sizeof (GTM_Sequence)); + memcpy(&maxval, pq_getmsgbytes(message, sizeof (GTM_Sequence)), + sizeof (GTM_Sequence)); + memcpy(&startval, pq_getmsgbytes(message, sizeof (GTM_Sequence)), + sizeof (GTM_Sequence)); + memcpy(&lastval, pq_getmsgbytes(message, sizeof (GTM_Sequence)), + sizeof (GTM_Sequence)); + + cycle = pq_getmsgbyte(message); + is_restart = pq_getmsgbyte(message); + + /* + * We must use the TopMostMemoryContext because the sequence information is + * not bound to a thread and can outlive any of the thread specific + * contextes. + */ + oldContext = MemoryContextSwitchTo(TopMostMemoryContext); + + if (GTM_SeqAlter(&seqkey, increment, minval, maxval, startval, lastval, cycle, is_restart)) + ereport(ERROR, + (errcode, + errmsg("Failed to open a new sequence"))); + + MemoryContextSwitchTo(oldContext); + + pq_getmsgend(message); + + pq_beginmessage(&buf, 'S'); + pq_sendint(&buf, SEQUENCE_ALTER_RESULT, 4); + if (myport->is_proxy) + { + GTM_ProxyMsgHeader proxyhdr; + proxyhdr.ph_conid = myport->conn_id; + pq_sendbytes(&buf, (char *)&proxyhdr, sizeof (GTM_ProxyMsgHeader)); + } + pq_sendint(&buf, seqkey.gsk_keylen, 4); + pq_sendbytes(&buf, seqkey.gsk_key, seqkey.gsk_keylen); + pq_endmessage(myport, &buf); + + if (!myport->is_proxy) + pq_flush(myport); +} + + +/* * Process MSG_SEQUENCE_GET_CURRENT message */ void @@ -697,6 +915,63 @@ ProcessSequenceGetNextCommand(Port *myport, StringInfo message) } /* + * Process MSG_SEQUENCE_SET_VAL message + */ +void +ProcessSequenceSetValCommand(Port *myport, StringInfo message) +{ + GTM_SequenceKeyData seqkey; + GTM_Sequence nextval; + MemoryContext oldContext; + StringInfoData buf; + bool iscalled; + int errcode; + + /* + * Get the sequence key + */ + seqkey.gsk_keylen = pq_getmsgint(message, sizeof (seqkey.gsk_keylen)); + seqkey.gsk_key = (char *)pq_getmsgbytes(message, seqkey.gsk_keylen); + + /* Read parameters to be set */ + memcpy(&nextval, pq_getmsgbytes(message, sizeof (GTM_Sequence)), + sizeof (GTM_Sequence)); + + iscalled = pq_getmsgbyte(message); + + /* + * We must use the TopMostMemoryContext because the sequence information is + * not bound to a thread and can outlive any of the thread specific + * contextes. + */ + oldContext = MemoryContextSwitchTo(TopMostMemoryContext); + + if (GTM_SeqSetVal(&seqkey, nextval, iscalled)) + ereport(ERROR, + (errcode, + errmsg("Failed to set values of sequence"))); + + MemoryContextSwitchTo(oldContext); + + pq_getmsgend(message); + + pq_beginmessage(&buf, 'S'); + pq_sendint(&buf, SEQUENCE_SET_VAL_RESULT, 4); + if (myport->is_proxy) + { + GTM_ProxyMsgHeader proxyhdr; + proxyhdr.ph_conid = myport->conn_id; + pq_sendbytes(&buf, (char *)&proxyhdr, sizeof (GTM_ProxyMsgHeader)); + } + pq_sendint(&buf, seqkey.gsk_keylen, 4); + pq_sendbytes(&buf, seqkey.gsk_key, seqkey.gsk_keylen); + pq_endmessage(myport, &buf); + + if (!myport->is_proxy) + pq_flush(myport); +} + +/* * Process MSG_SEQUENCE_RESET message */ void @@ -764,6 +1039,58 @@ ProcessSequenceCloseCommand(Port *myport, StringInfo message) pq_flush(myport); } +/* + * Process MSG_SEQUENCE_RENAME message + */ +void +ProcessSequenceRenameCommand(Port *myport, StringInfo message) +{ + GTM_SequenceKeyData seqkey, newseqkey; + StringInfoData buf; + int errcode; + MemoryContext oldContext; + + /* get the message from backend */ + seqkey.gsk_keylen = pq_getmsgint(message, sizeof (seqkey.gsk_keylen)); + seqkey.gsk_key = (char *)pq_getmsgbytes(message, seqkey.gsk_keylen); + + /* Get the rest of the message, new name length and string with new name */ + newseqkey.gsk_keylen = pq_getmsgint(message, sizeof (newseqkey.gsk_keylen)); + newseqkey.gsk_key = (char *)pq_getmsgbytes(message, newseqkey.gsk_keylen); + + /* + * As when creating a sequence, we must use the TopMostMemoryContext + * because the sequence information is not bound to a thread and + * can outlive any of the thread specific contextes. + */ + oldContext = MemoryContextSwitchTo(TopMostMemoryContext); + + if ((errcode = GTM_SeqRename(&seqkey, &newseqkey))) + ereport(ERROR, + (errcode, + errmsg("Can not rename the sequence"))); + + MemoryContextSwitchTo(oldContext); + + pq_getmsgend(message); + + /* Send a SUCCESS message back to the client */ + pq_beginmessage(&buf, 'S'); + pq_sendint(&buf, SEQUENCE_RENAME_RESULT, 4); + if (myport->is_proxy) + { + GTM_ProxyMsgHeader proxyhdr; + proxyhdr.ph_conid = myport->conn_id; + pq_sendbytes(&buf, (char *)&proxyhdr, sizeof (GTM_ProxyMsgHeader)); + } + pq_sendint(&buf, newseqkey.gsk_keylen, 4); + pq_sendbytes(&buf, newseqkey.gsk_key, newseqkey.gsk_keylen); + pq_endmessage(myport, &buf); + + if (!myport->is_proxy) + pq_flush(myport); +} + void GTM_SaveSeqInfo(int ctlfd) { diff --git a/src/gtm/main/main.c b/src/gtm/main/main.c index 0ef09c4..667967a 100644 --- a/src/gtm/main/main.c +++ b/src/gtm/main/main.c @@ -72,7 +72,7 @@ static void ProcessCommand(Port *myport, StringInfo input_message); static void ProcessCoordinatorCommand(Port *myport, GTM_MessageType mtype, StringInfo message); static void ProcessTransactionCommand(Port *myport, GTM_MessageType mtype, StringInfo message); static void ProcessSnapshotCommand(Port *myport, GTM_MessageType mtype, StringInfo message); -static void ProcessSeqeunceCommand(Port *myport, GTM_MessageType mtype, StringInfo message); +static void ProcessSequenceCommand(Port *myport, GTM_MessageType mtype, StringInfo message); static void ProcessQueryCommand(Port *myport, GTM_MessageType mtype, StringInfo message); static void GTM_RegisterCoordinator(Port *myport, GTM_CoordinatorId coordinator_id); @@ -761,16 +761,16 @@ ProcessCommand(Port *myport, StringInfo input_message) switch (mtype) { - case MSG_UNREGISTER_COORD: + case MSG_UNREGISTER_COORD: ProcessCoordinatorCommand(myport, mtype, input_message); break; - case MSG_TXN_BEGIN: - case MSG_TXN_BEGIN_GETGXID: - case MSG_TXN_BEGIN_GETGXID_AUTOVACUUM: - case MSG_TXN_PREPARE: - case MSG_TXN_COMMIT: - case MSG_TXN_ROLLBACK: + case MSG_TXN_BEGIN: + case MSG_TXN_BEGIN_GETGXID: + case MSG_TXN_BEGIN_GETGXID_AUTOVACUUM: + case MSG_TXN_PREPARE: + case MSG_TXN_COMMIT: + case MSG_TXN_ROLLBACK: case MSG_TXN_GET_GXID: case MSG_TXN_BEGIN_GETGXID_MULTI: case MSG_TXN_COMMIT_MULTI: @@ -778,18 +778,22 @@ ProcessCommand(Port *myport, StringInfo input_message) ProcessTransactionCommand(myport, mtype, input_message); break; - case MSG_SNAPSHOT_GET: + case MSG_SNAPSHOT_GET: case MSG_SNAPSHOT_GXID_GET: case MSG_SNAPSHOT_GET_MULTI: ProcessSnapshotCommand(myport, mtype, input_message); break; - case MSG_SEQUENCE_INIT: + case MSG_SEQUENCE_INIT: case MSG_SEQUENCE_GET_CURRENT: case MSG_SEQUENCE_GET_NEXT: + case MSG_SEQUENCE_GET_LAST: + case MSG_SEQUENCE_SET_VAL: case MSG_SEQUENCE_RESET: case MSG_SEQUENCE_CLOSE: - ProcessSeqeunceCommand(myport, mtype, input_message); + case MSG_SEQUENCE_RENAME: + case MSG_SEQUENCE_ALTER: + ProcessSequenceCommand(myport, mtype, input_message); break; case MSG_TXN_GET_STATUS: @@ -1003,14 +1007,18 @@ ProcessSnapshotCommand(Port *myport, GTM_MessageType mtype, StringInfo message) } static void -ProcessSeqeunceCommand(Port *myport, GTM_MessageType mtype, StringInfo message) +ProcessSequenceCommand(Port *myport, GTM_MessageType mtype, StringInfo message) { switch (mtype) { - case MSG_SEQUENCE_INIT: + case MSG_SEQUENCE_INIT: ProcessSequenceInitCommand(myport, message); break; + case MSG_SEQUENCE_ALTER: + ProcessSequenceAlterCommand(myport, message); + break; + case MSG_SEQUENCE_GET_CURRENT: ProcessSequenceGetCurrentCommand(myport, message); break; @@ -1019,6 +1027,10 @@ ProcessSeqeunceCommand(Port *myport, GTM_MessageType mtype, StringInfo message) ProcessSequenceGetNextCommand(myport, message); break; + case MSG_SEQUENCE_SET_VAL: + ProcessSequenceSetValCommand(myport, message); + break; + case MSG_SEQUENCE_RESET: ProcessSequenceResetCommand(myport, message); break; @@ -1027,6 +1039,10 @@ ProcessSeqeunceCommand(Port *myport, GTM_MessageType mtype, StringInfo message) ProcessSequenceCloseCommand(myport, message); break; + case MSG_SEQUENCE_RENAME: + ProcessSequenceRenameCommand(myport, message); + break; + default: Assert(0); /* Shouldn't come here.. keep compiler quite */ } diff --git a/src/include/access/gtm.h b/src/include/access/gtm.h index 66ca3f1..3831f09 100644 --- a/src/include/access/gtm.h +++ b/src/include/access/gtm.h @@ -25,9 +25,17 @@ extern GlobalTransactionId BeginTranAutovacuumGTM(void); extern int CommitTranGTM(GlobalTransactionId gxid); extern int RollbackTranGTM(GlobalTransactionId gxid); extern GTM_Snapshot GetSnapshotGTM(GlobalTransactionId gxid, bool canbe_grouped); + +/* Sequence interface APIs with GTM */ +extern GTM_Sequence GetCurrentValGTM(char *seqname); extern GTM_Sequence GetNextValGTM(char *seqname); +extern int SetValGTM(char *seqname, GTM_Sequence nextval, bool iscalled); extern int CreateSequenceGTM(char *seqname, GTM_Sequence increment, GTM_Sequence minval, GTM_Sequence maxval, GTM_Sequence startval, bool cycle); +extern int AlterSequenceGTM(char *seqname, GTM_Sequence increment, + GTM_Sequence minval, GTM_Sequence maxval, GTM_Sequence startval, + GTM_Sequence lastval, bool cycle, bool is_restart); extern int DropSequenceGTM(char *seqname); +extern int RenameSequenceGTM(char *seqname, const char *newseqname); #endif /* ACCESS_GTM_H */ diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h index 8a2c506..b5bb7d9 100644 --- a/src/include/commands/sequence.h +++ b/src/include/commands/sequence.h @@ -99,4 +99,8 @@ extern void AlterSequenceInternal(Oid relid, List *options); extern void seq_redo(XLogRecPtr lsn, XLogRecord *rptr); extern void seq_desc(StringInfo buf, uint8 xl_info, char *rec); +#ifdef PGXC +extern char *GetGlobalSeqName(Relation rel, const char *new_seqname); +#endif + #endif /* SEQUENCE_H */ diff --git a/src/include/gtm/gtm_client.h b/src/include/gtm/gtm_client.h index 0ccc232..05e44bf 100644 --- a/src/include/gtm/gtm_client.h +++ b/src/include/gtm/gtm_client.h @@ -120,9 +120,14 @@ GTM_SnapshotData *get_snapshot(GTM_Conn *conn, GlobalTransactionId gxid, int open_sequence(GTM_Conn *conn, GTM_SequenceKey key, GTM_Sequence increment, GTM_Sequence minval, GTM_Sequence maxval, GTM_Sequence startval, bool cycle); +int alter_sequence(GTM_Conn *conn, GTM_SequenceKey key, GTM_Sequence increment, + GTM_Sequence minval, GTM_Sequence maxval, + GTM_Sequence startval, GTM_Sequence lastval, bool cycle, bool is_restart); int close_sequence(GTM_Conn *conn, GTM_SequenceKey key); +int rename_sequence(GTM_Conn *conn, GTM_SequenceKey key, GTM_SequenceKey newkey); GTM_Sequence get_current(GTM_Conn *conn, GTM_SequenceKey key); GTM_Sequence get_next(GTM_Conn *conn, GTM_SequenceKey key); +int set_val(GTM_Conn *conn, GTM_SequenceKey key, GTM_Sequence nextval, bool is_called); int reset_sequence(GTM_Conn *conn, GTM_SequenceKey key); diff --git a/src/include/gtm/gtm_msg.h b/src/include/gtm/gtm_msg.h index cae0614..e76e762 100644 --- a/src/include/gtm/gtm_msg.h +++ b/src/include/gtm/gtm_msg.h @@ -34,11 +34,15 @@ typedef enum GTM_MessageType MSG_SEQUENCE_INIT, /* Initialize a new global sequence */ MSG_SEQUENCE_GET_CURRENT,/* Get the current value of sequence */ MSG_SEQUENCE_GET_NEXT, /* Get the next sequence value of sequence */ + MSG_SEQUENCE_GET_LAST, /* Get the last sequence value of sequence */ + MSG_SEQUENCE_SET_VAL, /* Set values for sequence */ MSG_SEQUENCE_RESET, /* Reset the sequence */ MSG_SEQUENCE_CLOSE, /* Close a previously inited sequence */ + MSG_SEQUENCE_RENAME, /* Rename a sequence */ + MSG_SEQUENCE_ALTER, /* Alter a sequence */ MSG_TXN_GET_STATUS, /* Get status of a given transaction */ MSG_TXN_GET_ALL_PREPARED, /* Get information about all outstanding - * prepared transactions */ + * prepared transactions */ MSG_TXN_BEGIN_GETGXID_AUTOVACUUM, /* Start a new transaction and get GXID for autovacuum */ MSG_DATA_FLUSH, /* flush pending data */ MSG_BACKEND_DISCONNECT, /* tell GTM that the backend diconnected from the proxy */ @@ -66,8 +70,12 @@ typedef enum GTM_ResultType SEQUENCE_INIT_RESULT, SEQUENCE_GET_CURRENT_RESULT, SEQUENCE_GET_NEXT_RESULT, + SEQUENCE_GET_LAST_RESULT, + SEQUENCE_SET_VAL_RESULT, SEQUENCE_RESET_RESULT, SEQUENCE_CLOSE_RESULT, + SEQUENCE_RENAME_RESULT, + SEQUENCE_ALTER_RESULT, TXN_GET_STATUS_RESULT, TXN_GET_ALL_PREPARED_RESULT, TXN_BEGIN_GETGXID_AUTOVACUUM_RESULT, diff --git a/src/include/gtm/gtm_seq.h b/src/include/gtm/gtm_seq.h index 6cb8cb3..7dc1e3e 100644 --- a/src/include/gtm/gtm_seq.h +++ b/src/include/gtm/gtm_seq.h @@ -23,6 +23,7 @@ typedef struct GTM_SeqInfo GTM_SequenceKey gs_key; GTM_Sequence gs_value; GTM_Sequence gs_init_value; + GTM_Sequence gs_last_value; GTM_Sequence gs_increment_by; GTM_Sequence gs_min_value; GTM_Sequence gs_max_value; @@ -57,17 +58,30 @@ int GTM_SeqOpen(GTM_SequenceKey seqkey, GTM_Sequence maxval, GTM_Sequence startval, bool cycle); -int GTM_SeqClose(GTM_SequenceKey sqkey); +int GTM_SeqAlter(GTM_SequenceKey seqkey, + GTM_Sequence increment_by, + GTM_Sequence minval, + GTM_Sequence maxval, + GTM_Sequence startval, + GTM_Sequence lastval, + bool cycle, + bool is_restart); +int GTM_SeqClose(GTM_SequenceKey seqkey); +int GTM_SeqRename(GTM_SequenceKey seqkey, GTM_SequenceKey newseqkey); GTM_Sequence GTM_SeqGetNext(GTM_SequenceKey seqkey); GTM_Sequence GTM_SeqGetCurrent(GTM_SequenceKey seqkey); +int GTM_SeqSetVal(GTM_SequenceKey seqkey, GTM_Sequence nextval, bool iscalled); int GTM_SeqReset(GTM_SequenceKey seqkey); void ProcessSequenceInitCommand(Port *myport, StringInfo message); void ProcessSequenceGetCurrentCommand(Port *myport, StringInfo message); void ProcessSequenceGetNextCommand(Port *myport, StringInfo message); +void ProcessSequenceSetValCommand(Port *myport, StringInfo message); void ProcessSequenceResetCommand(Port *myport, StringInfo message); void ProcessSequenceCloseCommand(Port *myport, StringInfo message); +void ProcessSequenceRenameCommand(Port *myport, StringInfo message); +void ProcessSequenceAlterCommand(Port *myport, StringInfo message); void GTM_SaveSeqInfo(int ctlfd); void GTM_RestoreSeqInfo(int ctlfd); ----------------------------------------------------------------------- Summary of changes: src/backend/access/transam/gtm.c | 76 ++++++++- src/backend/commands/sequence.c | 191 ++++++++++++++++++++-- src/backend/commands/tablecmds.c | 31 ++++- src/backend/pgxc/plan/planner.c | 81 ++-------- src/gtm/client/fe-protocol.c | 8 + src/gtm/client/gtm_client.c | 123 ++++++++++++++- src/gtm/main/gtm_seq.c | 333 +++++++++++++++++++++++++++++++++++++- src/gtm/main/main.c | 42 ++++-- src/include/access/gtm.h | 8 + src/include/commands/sequence.h | 4 + src/include/gtm/gtm_client.h | 5 + src/include/gtm/gtm_msg.h | 10 +- src/include/gtm/gtm_seq.h | 16 ++- 13 files changed, 823 insertions(+), 105 deletions(-) hooks/post-receive -- Postgres-XC |