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
|
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 |
From: mason_s <ma...@us...> - 2010-06-16 15:25:18
|
Project "Postgres-XC". The branch, master has been updated via a216b00661e2b76267681bade35a620566fe9345 (commit) from a0429d3f49568868602efb8881a79c3716201134 (commit) - Log ----------------------------------------------------------------- commit a216b00661e2b76267681bade35a620566fe9345 Author: Mason S <masonsharp@mason-sharps-macbook.local> Date: Wed Jun 16 11:24:34 2010 -0400 Do not yet allow creation of temp tables until we properly handle them. diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index cc8a664..0d73fc9 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -1601,6 +1601,15 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; break; + case T_CreateStmt: + if (((CreateStmt *)parsetree)->relation->istemp) + ereport(ERROR, + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), + (errmsg("Temp tables are not yet supported.")))); + + query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; + break; + /* * Statements that we execute on both the Coordinator and Data Nodes */ @@ -1626,7 +1635,6 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) case T_CreateOpClassStmt: case T_CreateOpFamilyStmt: case T_CreatePLangStmt: - case T_CreateStmt: case T_CreateSchemaStmt: case T_DeallocateStmt: /* Allow for DEALLOCATE ALL */ case T_DiscardStmt: ----------------------------------------------------------------------- Summary of changes: src/backend/pgxc/plan/planner.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: mason_s <ma...@us...> - 2010-06-16 15:08:42
|
Project "Postgres-XC". The branch, master has been updated via a0429d3f49568868602efb8881a79c3716201134 (commit) from b65c64d294d9a91583534d951b758c5bccacea48 (commit) - Log ----------------------------------------------------------------- commit a0429d3f49568868602efb8881a79c3716201134 Author: Mason S <masonsharp@mason-sharps-macbook.local> Date: Wed Jun 16 11:07:40 2010 -0400 Do not allow WITH RECURSIVE or windowing functions until we add support for them. diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index 78c13a1..cc8a664 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -403,7 +403,7 @@ get_plan_nodes_insert(Query *query) if (!IsA(tle->expr, Const)) { - eval_expr = eval_const_expressions(NULL, tle->expr); + eval_expr = eval_const_expressions(NULL, (Node *) tle->expr); checkexpr = get_numeric_constant(eval_expr); } @@ -540,7 +540,7 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod if (!IsA(arg2, Const)) { /* this gets freed when the memory context gets freed */ - Expr *eval_expr = eval_const_expressions(NULL, arg2); + Expr *eval_expr = eval_const_expressions(NULL, (Node *) arg2); checkexpr = get_numeric_constant(eval_expr); } @@ -1413,6 +1413,31 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) case T_DeleteStmt: /* just use first one in querytree_list */ query = (Query *) linitial(querytree_list); + + /* Perform some checks to make sure we can support the statement */ + if (nodeTag(parsetree) == T_SelectStmt) + { + if (query->intoClause) + ereport(ERROR, + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), + (errmsg("INTO clause not yet supported")))); + + if (query->setOperations) + ereport(ERROR, + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), + (errmsg("UNION, INTERSECT and EXCEPT are not yet supported")))); + + if (query->hasRecursive) + ereport(ERROR, + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), + (errmsg("WITH RECURSIVE not yet supported")))); + + if (query->hasWindowFuncs) + ereport(ERROR, + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), + (errmsg("Window functions not yet supported")))); + } + query_step->exec_nodes = get_plan_nodes_command(query_plan, query); if (query_step->exec_nodes) @@ -1463,16 +1488,6 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) */ if (nodeTag(parsetree) == T_SelectStmt) { - if (query->intoClause) - ereport(ERROR, - (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), - (errmsg("INTO clause not yet supported")))); - - if (query->setOperations) - ereport(ERROR, - (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), - (errmsg("UNION, INTERSECT and EXCEPT are not yet supported")))); - if (StrictStatementChecking && query_step->exec_nodes && list_length(query_step->exec_nodes->nodelist) > 1) { ----------------------------------------------------------------------- Summary of changes: src/backend/pgxc/plan/planner.c | 39 +++++++++++++++++++++++++++------------ 1 files changed, 27 insertions(+), 12 deletions(-) hooks/post-receive -- Postgres-XC |
From: mason_s <ma...@us...> - 2010-06-16 14:04:53
|
Project "Postgres-XC". The branch, master has been updated via b65c64d294d9a91583534d951b758c5bccacea48 (commit) from 4a16b67e0239abda5f2ca8ec45489b7fc906ec4b (commit) - Log ----------------------------------------------------------------- commit b65c64d294d9a91583534d951b758c5bccacea48 Author: Mason S <masonsharp@mason-sharps-macbook.local> Date: Wed Jun 16 10:02:05 2010 -0400 When using hash distributed tables and a value that corresponds to the distribution column, if it is an expression containing constants, try and evaluate it to determine the destination execution node. This corresponds to bug 3008130. diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index 5e318dc..78c13a1 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -23,6 +23,7 @@ #include "lib/stringinfo.h" #include "nodes/nodeFuncs.h" #include "nodes/parsenodes.h" +#include "optimizer/clauses.h" #include "parser/parse_agg.h" #include "parser/parse_coerce.h" #include "pgxc/locator.h" @@ -257,7 +258,6 @@ free_join_list(void) static Expr * get_numeric_constant(Expr *expr) { - if (expr == NULL) return NULL; @@ -356,6 +356,7 @@ get_plan_nodes_insert(Query *query) ListCell *lc; long part_value; long *part_value_ptr = NULL; + Expr *eval_expr = NULL; /* Looks complex (correlated?) - best to skip */ if (query->jointree != NULL && query->jointree->fromlist != NULL) @@ -398,7 +399,13 @@ get_plan_nodes_insert(Query *query) if (strcmp(tle->resname, rel_loc_info->partAttrName) == 0) { /* We may have a cast, try and handle it */ - Expr *checkexpr = get_numeric_constant(tle->expr); + Expr *checkexpr = tle->expr; + + if (!IsA(tle->expr, Const)) + { + eval_expr = eval_const_expressions(NULL, tle->expr); + checkexpr = get_numeric_constant(eval_expr); + } if (checkexpr == NULL) break; /* no constant */ @@ -425,6 +432,9 @@ get_plan_nodes_insert(Query *query) /* single call handles both replicated and partitioned types */ exec_nodes = GetRelationNodes(rel_loc_info, part_value_ptr, false); + if (eval_expr) + pfree(eval_expr); + return exec_nodes; } @@ -524,9 +534,15 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod return false; /* Look at other argument */ + checkexpr = arg2; - /* We may have a cast, try and handle it */ - checkexpr = get_numeric_constant(arg2); + /* We may have a cast or expression, try and handle it */ + if (!IsA(arg2, Const)) + { + /* this gets freed when the memory context gets freed */ + Expr *eval_expr = eval_const_expressions(NULL, arg2); + checkexpr = get_numeric_constant(eval_expr); + } if (checkexpr != NULL) arg2 = checkexpr; ----------------------------------------------------------------------- Summary of changes: src/backend/pgxc/plan/planner.c | 24 ++++++++++++++++++++---- 1 files changed, 20 insertions(+), 4 deletions(-) hooks/post-receive -- Postgres-XC |
From: mason_s <ma...@us...> - 2010-06-15 18:59:22
|
Project "Postgres-XC". The branch, master has been updated via 4a16b67e0239abda5f2ca8ec45489b7fc906ec4b (commit) from ffe244ab59c464283ac1833e13377782bee1c122 (commit) - Log ----------------------------------------------------------------- commit 4a16b67e0239abda5f2ca8ec45489b7fc906ec4b Author: Mason S <masonsharp@mason-sharps-macbook.local> Date: Tue Jun 15 14:54:23 2010 -0400 Add support for views. A view is in effect rewritten into a FROM clause subquery, so we also add support of detecting safe FROM clause subqueries. We check after the query tree is rewritten if the query is safe to execute in a single step, include FROM clause subqueries. If not, we do not allow it. diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index cc4413c..a8f9d30 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -878,6 +878,12 @@ AddRelationDistribution (Oid relid, case DISTTYPE_HASH: /* User specified hash column, validate */ attnum = get_attnum(relid, distributeby->colname); + if (!attnum) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("Invalid distribution column specified"))); + } if (!IsHashDistributable(descriptor->attrs[attnum-1]->atttypid)) { diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index 13a0f8b..5e318dc 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -86,6 +86,15 @@ typedef struct PGXCJoinType join_type; } PGXC_Join; +/* used for base column in an expression */ +typedef struct ColumnBase +{ + int relid; + char *relname; + char *relalias; + char *colname; +} ColumnBase; + /* A list of List*'s, one for each relation. */ List *join_list = NULL; @@ -96,6 +105,17 @@ bool StrictStatementChecking = true; bool StrictSelectChecking = false; /* + * True if both lists contain only one node and are the same + */ +static bool +same_single_node (List *nodelist1, List *nodelist2) +{ + return nodelist1 && list_length(nodelist1) == 1 + && nodelist2 && list_length(nodelist2) == 1 + && linitial_int(nodelist1) != linitial_int(nodelist2); +} + +/* * Create a new join struct for tracking how relations are joined */ static PGXC_Join * @@ -224,7 +244,6 @@ free_join_list(void) if (join_list == NULL) return; - /* free all items in list including PGXC_Join struct */ list_free_deep(join_list); } @@ -269,7 +288,7 @@ get_numeric_constant(Expr *expr) * type, like a join, and we need to then look at the joinaliasvars * to determine what the base table and column really is. */ -static Var * +static ColumnBase* get_base_var(Var *var, List *rtables) { RangeTblEntry *rte; @@ -282,18 +301,45 @@ get_base_var(Var *var, List *rtables) rte = list_nth(rtables, var->varno - 1); if (rte->rtekind == RTE_RELATION) - return var; + { + ColumnBase *column_base = (ColumnBase *) palloc0(sizeof(ColumnBase)); + + column_base->relid = rte->relid; + column_base->relname = get_rel_name(rte->relid); + column_base->colname = strVal(list_nth(rte->eref->colnames, + var->varattno - 1)); + column_base->relalias = rte->eref->aliasname; + return column_base; + } else if (rte->rtekind == RTE_JOIN) { Var *colvar = list_nth(rte->joinaliasvars, var->varattno - 1); /* continue resolving recursively */ return get_base_var(colvar, rtables); + //may need to set this, toocolumn_base->relalias = rte->eref->aliasname; } - else + else if (rte->rtekind == RTE_SUBQUERY) { - return NULL; + /* + * Handle views like select * from v1 where col1 = 1 + * where col1 is partition column of base relation + */ + /* the varattno corresponds with the subquery's target list (projections) */ + TargetEntry *tle = list_nth(rte->subquery->targetList, var->varattno - 1); /* or varno? */ + + if (!IsA(tle->expr, Var)) + return NULL; /* not column based expressoin, return */ + else + { + Var *colvar = (Var *) tle->expr; + + /* continue resolving recursively */ + return get_base_var(colvar, rte->subquery->rtable); + } } + + return NULL; } @@ -316,10 +362,11 @@ get_plan_nodes_insert(Query *query) return NULL; /* Make sure there is just one table */ - if (query->rtable == NULL || query->rtable->length != 1) + if (query->rtable == NULL) return NULL; - rte = (RangeTblEntry *) lfirst(list_head(query->rtable)); + rte = (RangeTblEntry *) list_nth(query->rtable, query->resultRelation - 1); + if (rte != NULL && rte->rtekind != RTE_RELATION) /* Bad relation type */ @@ -402,10 +449,6 @@ get_plan_nodes_insert(Query *query) static bool examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_node) { - char *rel_name, - *rel_name2; - char *col_name, - *col_name2; RelationLocInfo *rel_loc_info1, *rel_loc_info2; Const *constant; @@ -472,23 +515,14 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod /* Look for a table */ if (IsA(arg1, Var)) { - RangeTblEntry *rte1, - *rte2; - /* get the RangeTableEntry */ Var *colvar = (Var *) arg1; - colvar = get_base_var(colvar, rtables); + ColumnBase *column_base = get_base_var(colvar, rtables); - if (!colvar) + if (!column_base) return false; - rte1 = list_nth(rtables, colvar->varno - 1); - - rel_name = get_rel_name(rte1->relid); - col_name = strVal(list_nth(rte1->eref->colnames, - colvar->varattno - 1)); - /* Look at other argument */ /* We may have a cast, try and handle it */ @@ -502,21 +536,21 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod /* We have column = literal. Check if partitioned case */ constant = (Const *) arg2; - rel_loc_info1 = GetRelationLocInfo(rte1->relid); + rel_loc_info1 = GetRelationLocInfo(column_base->relid); if (!rel_loc_info1) return false; /* If hash partitioned, check if the part column was used */ - if (IsHashColumn(rel_loc_info1, col_name)) + if (IsHashColumn(rel_loc_info1, column_base->colname)) { /* add to partitioned literal join conditions */ Literal_Comparison *lit_comp = palloc(sizeof(Literal_Comparison)); - lit_comp->relid = rte1->relid; + lit_comp->relid = column_base->relid; lit_comp->rel_loc_info = rel_loc_info1; - lit_comp->col_name = col_name; + lit_comp->col_name = column_base->colname; lit_comp->constant = constant->constvalue; conditions->partitioned_literal_comps = lappend( @@ -537,23 +571,22 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod else if (IsA(arg2, Var)) { PGXC_Join *pgxc_join; + ColumnBase *column_base2; Var *colvar2 = (Var *) arg2; - rel_loc_info1 = GetRelationLocInfo(rte1->relid); + rel_loc_info1 = GetRelationLocInfo(column_base->relid); if (!rel_loc_info1) return false; - colvar2 = get_base_var(colvar2, rtables); - if (!colvar2) + column_base2 = get_base_var(colvar2, rtables); + if (!column_base2) return false; - rte2 = list_nth(rtables, colvar2->varno - 1); - rel_name2 = get_rel_name(rte2->relid); - rel_loc_info2 = GetRelationLocInfo(rte2->relid); + rel_loc_info2 = GetRelationLocInfo(column_base2->relid); /* get data struct about these two relations joining */ - pgxc_join = find_or_create_pgxc_join(rte1->relid, rte1->eref->aliasname, - rte2->relid, rte2->eref->aliasname); + pgxc_join = find_or_create_pgxc_join(column_base->relid, column_base->relalias, + column_base2->relid, column_base2->relalias); /* * pgxc_join->condition_list = @@ -569,7 +602,7 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod if (rel_loc_info2->locatorType != LOCATOR_TYPE_REPLICATED) { /* Note other relation, saves us work later. */ - conditions->base_rel_name = rel_name2; + conditions->base_rel_name = column_base2->relname; conditions->base_rel_loc_info = rel_loc_info2; if (rel_loc_info1) FreeRelationLocInfo(rel_loc_info1); @@ -577,7 +610,7 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod if (conditions->base_rel_name == NULL) { - conditions->base_rel_name = rel_name; + conditions->base_rel_name = column_base->relname; conditions->base_rel_loc_info = rel_loc_info1; if (rel_loc_info2) FreeRelationLocInfo(rel_loc_info2); @@ -595,7 +628,7 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod lappend(conditions->replicated_joins, opexpr); /* other relation not replicated, note it for later */ - conditions->base_rel_name = rel_name; + conditions->base_rel_name = column_base->relname; conditions->base_rel_loc_info = rel_loc_info1; /* note nature of join between the two relations */ @@ -613,11 +646,8 @@ examine_conditions(Special_Conditions *conditions, List *rtables, Node *expr_nod * PGXCTODO - for the prototype, we assume all partitioned * tables are on the same nodes. */ - col_name2 = strVal(list_nth(rte2->eref->colnames, - colvar2->varattno - 1)); - - if (IsHashColumn(rel_loc_info1, col_name) - && IsHashColumn(rel_loc_info2, col_name2)) + if (IsHashColumn(rel_loc_info1, column_base->colname) + && IsHashColumn(rel_loc_info2, column_base2->colname)) { /* We found a partitioned join */ conditions->partitioned_parent_child = @@ -740,13 +770,16 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) ListCell *lc, *item; Special_Conditions *special_conditions; - OpExpr *opexpr; + OpExpr *opexpr; Var *colvar; RelationLocInfo *rel_loc_info; - Exec_Nodes *exec_nodes; - Exec_Nodes *test_exec_nodes; + Exec_Nodes *test_exec_nodes = NULL; + Exec_Nodes *exec_nodes = NULL; + Exec_Nodes *current_nodes = NULL; + Exec_Nodes *from_query_nodes = NULL; TableUsageType table_usage_type = TABLE_USAGE_TYPE_NO_TABLE; TableUsageType current_usage_type = TABLE_USAGE_TYPE_NO_TABLE; + int from_subquery_count = 0; exec_nodes = NULL; @@ -778,13 +811,11 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) exec_nodes = (Exec_Nodes *) palloc0(sizeof(Exec_Nodes)); exec_nodes->tableusagetype = TABLE_USAGE_TYPE_PGCATALOG; free_special_relations(special_conditions); - free_join_list(); return exec_nodes; } /* complicated */ free_special_relations(special_conditions); - free_join_list(); return NULL; } } @@ -797,20 +828,49 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) if (rte->rtekind == RTE_SUBQUERY) { + from_subquery_count++; /* * Recursively call for subqueries. * Note this also works for views, which are rewritten as subqueries. */ - Exec_Nodes *sub_nodes = get_plan_nodes(query_plan, rte->subquery, isRead); - if (sub_nodes) - current_usage_type = sub_nodes->tableusagetype; + current_nodes = get_plan_nodes(query_plan, rte->subquery, isRead); + if (current_nodes) + current_usage_type = current_nodes->tableusagetype; else { /* could be complicated */ free_special_relations(special_conditions); - free_join_list(); return NULL; } + + /* We compare to make sure that the subquery is safe to execute with previous- + * we may have multiple ones in the FROM clause. + * We handle the simple case of allowing multiple subqueries in the from clause, + * but only allow one of them to not contain replicated tables + */ + if (!from_query_nodes) + from_query_nodes = current_nodes; + else if (current_nodes->tableusagetype == TABLE_USAGE_TYPE_USER_REPLICATED) + { + /* ok, safe */ + if (!from_query_nodes) + from_query_nodes = current_nodes; + } + else + { + if (from_query_nodes->tableusagetype == TABLE_USAGE_TYPE_USER_REPLICATED) + from_query_nodes = current_nodes; + else + { + /* Allow if they are both using one node, and the same one */ + if (!same_single_node (from_query_nodes->nodelist, current_nodes->nodelist)) + { + /* Complicated */ + free_special_relations(special_conditions); + return NULL; + } + } + } } else if (rte->rtekind == RTE_RELATION) { @@ -818,7 +878,7 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) if (get_rel_namespace(rte->relid) == PG_CATALOG_NAMESPACE) current_usage_type = TABLE_USAGE_TYPE_PGCATALOG; else - current_usage_type = TABLE_USAGE_TYPE_USER_TABLE; + current_usage_type = TABLE_USAGE_TYPE_USER; } else if (rte->rtekind == RTE_FUNCTION) { @@ -827,13 +887,17 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) if (get_func_namespace(funcexpr->funcid) == PG_CATALOG_NAMESPACE) current_usage_type = TABLE_USAGE_TYPE_PGCATALOG; else - current_usage_type = TABLE_USAGE_TYPE_USER_TABLE; + { + //current_usage_type = TABLE_USAGE_TYPE_USER; + /* Complicated */ + free_special_relations(special_conditions); + return NULL; + } } else { /* could be complicated */ free_special_relations(special_conditions); - free_join_list(); return NULL; } @@ -844,7 +908,6 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) { /* mixed- too complicated for us for now */ free_special_relations(special_conditions); - free_join_list(); return NULL; } } @@ -852,7 +915,6 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) { /* could be complicated */ free_special_relations(special_conditions); - free_join_list(); return NULL; } } @@ -871,7 +933,6 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) { /* if cross joins may exist, just return NULL */ free_special_relations(special_conditions); - free_join_list(); return NULL; } @@ -886,7 +947,6 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) if (pgxcjoin->join_type == JOIN_OTHER) { free_special_relations(special_conditions); - free_join_list(); return NULL; } } @@ -897,36 +957,64 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) if (special_conditions->partitioned_parent_child == NULL && special_conditions->partitioned_literal_comps == NULL) { - if (special_conditions->replicated_joins == NULL - && (query->rtable == NULL || query->rtable->length > 1)) + /* + * We have either a single table, just replicated tables, or a + * table that just joins with replicated tables, or something + * complicated. + */ - /* - * This is too complicated for a single step, or there is no FROM - * clause - */ - exec_nodes = NULL; - else + /* See if we noted a table earlier to use */ + rel_loc_info = special_conditions->base_rel_loc_info; + + if (rel_loc_info == NULL) { - /* - * We have either a single table, just replicated tables, or a - * table that just joins with replicated tables. - */ + RangeTblEntry *rtesave = NULL; - /* See if we noted a table earlier to use */ - rel_loc_info = special_conditions->base_rel_loc_info; + foreach(lc, query->rtable) + { + rte = (RangeTblEntry *) lfirst(lc); + + /* + * If the query is rewritten (which can be due to rules or views), + * ignore extra stuff. Also ignore subqueries we have processed + */ + if (!rte->inFromCl || rte->rtekind != RTE_RELATION) + continue; + + /* PGXCTODO - handle RTEs that are functions */ + if (rtesave) + /* + * Too complicated, we have multiple relations that still + * cannot be joined safely + */ + return NULL; + + rtesave = rte; + } - if (rel_loc_info == NULL) + if (rtesave) { /* a single table, just grab it */ - rte = (RangeTblEntry *) linitial(query->rtable); - rel_loc_info = GetRelationLocInfo(rte->relid); + rel_loc_info = GetRelationLocInfo(rtesave->relid); if (!rel_loc_info) return NULL; - } + exec_nodes = GetRelationNodes(rel_loc_info, NULL, isRead); + } + } + else + { exec_nodes = GetRelationNodes(rel_loc_info, NULL, isRead); - exec_nodes->tableusagetype = table_usage_type; + } + + /* Note replicated table usage for determining safe queries */ + if (exec_nodes) + { + if (table_usage_type == TABLE_USAGE_TYPE_USER && IsReplicated(rel_loc_info)) + table_usage_type = TABLE_USAGE_TYPE_USER_REPLICATED; + else + exec_nodes->tableusagetype = table_usage_type; } } /* check for partitioned col comparison against a literal */ @@ -950,15 +1038,10 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) exec_nodes = test_exec_nodes; else { - if ((exec_nodes && list_length(exec_nodes->nodelist) > 1) - || (test_exec_nodes && list_length(test_exec_nodes->nodelist) > 1)) - /* there should only be one */ - exec_nodes = NULL; - else + if (!same_single_node(exec_nodes->nodelist, test_exec_nodes->nodelist)) { - /* Make sure they use the same nodes */ - if (linitial_int(test_exec_nodes->nodelist) != linitial_int(exec_nodes->nodelist)) - exec_nodes = NULL; + free_special_relations(special_conditions); + return NULL; } } } @@ -970,14 +1053,18 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) * no partitioned column comparison condition with a literal. We just * use one of the tables as a basis for node determination. */ + ColumnBase *column_base; + opexpr = (OpExpr *) linitial(special_conditions->partitioned_parent_child); colvar = (Var *) linitial(opexpr->args); /* get the RangeTableEntry */ - rte = list_nth(query->rtable, colvar->varno - 1); - rel_loc_info = GetRelationLocInfo(rte->relid); + column_base = get_base_var(colvar, query->rtable); + if (!column_base) + return false; + rel_loc_info = GetRelationLocInfo(column_base->relid); if (!rel_loc_info) return false; @@ -985,7 +1072,29 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) exec_nodes->tableusagetype = table_usage_type; } free_special_relations(special_conditions); - free_join_list(); + + if (from_query_nodes) + { + if (!exec_nodes) + return from_query_nodes; + /* Just use exec_nodes if the from subqueries are all replicated or using the exact + * same node + */ + else if (from_query_nodes->tableusagetype == TABLE_USAGE_TYPE_USER_REPLICATED + || (same_single_node(from_query_nodes->nodelist, exec_nodes->nodelist))) + return exec_nodes; + else + { + /* We allow views, where the (rewritten) subquery may be on all nodes, but the parent + * query applies a condition on the from subquery. + */ + if (list_length(query->jointree->fromlist) == from_subquery_count + && list_length(exec_nodes->nodelist) == 1) + return exec_nodes; + } + /* Too complicated, give up */ + return NULL; + } return exec_nodes; } @@ -999,26 +1108,30 @@ get_plan_nodes(Query_Plan *query_plan, Query *query, bool isRead) static Exec_Nodes * get_plan_nodes_command(Query_Plan *query_plan, Query *query) { + Exec_Nodes *exec_nodes = NULL; switch (query->commandType) { case CMD_SELECT: - return get_plan_nodes(query_plan, query, true); + exec_nodes = get_plan_nodes(query_plan, query, true); + break; case CMD_INSERT: - return get_plan_nodes_insert(query); + exec_nodes = get_plan_nodes_insert(query); + break; case CMD_UPDATE: - /* treat as a select */ - return get_plan_nodes(query_plan, query, false); - case CMD_DELETE: /* treat as a select */ - return get_plan_nodes(query_plan, query, false); + exec_nodes = get_plan_nodes(query_plan, query, false); + break; default: return NULL; } + + free_join_list(); + return exec_nodes; } @@ -1498,6 +1611,7 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) case T_RemoveOpFamilyStmt: case T_TruncateStmt: case T_VariableSetStmt: + case T_ViewStmt: /* * Also support these, should help later with pg_restore, although @@ -1581,7 +1695,6 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) case T_PrepareStmt: case T_RuleStmt: case T_UnlistenStmt: - case T_ViewStmt: /* fall through */ default: /* Allow for override */ diff --git a/src/include/pgxc/locator.h b/src/include/pgxc/locator.h index 5fea37a..5ead756 100644 --- a/src/include/pgxc/locator.h +++ b/src/include/pgxc/locator.h @@ -25,6 +25,7 @@ #define HASH_SIZE 4096 #define HASH_MASK 0x00000FFF; +#define IsReplicated(x) (x->locatorType == LOCATOR_TYPE_REPLICATED) #include "utils/relcache.h" @@ -47,7 +48,8 @@ typedef enum { TABLE_USAGE_TYPE_NO_TABLE, TABLE_USAGE_TYPE_PGCATALOG, - TABLE_USAGE_TYPE_USER_TABLE, + TABLE_USAGE_TYPE_USER, + TABLE_USAGE_TYPE_USER_REPLICATED, /* based on a replicated table */ TABLE_USAGE_TYPE_MIXED } TableUsageType; ----------------------------------------------------------------------- Summary of changes: src/backend/catalog/heap.c | 6 + src/backend/pgxc/plan/planner.c | 303 +++++++++++++++++++++++++++------------ src/include/pgxc/locator.h | 4 +- 3 files changed, 217 insertions(+), 96 deletions(-) hooks/post-receive -- Postgres-XC |
From: mason_s <ma...@us...> - 2010-06-01 21:07:02
|
Project "Postgres-XC". The branch, master has been updated via ffe244ab59c464283ac1833e13377782bee1c122 (commit) from 63b0858e76a740e6b0a5e30fa27d7b1d761ac6af (commit) - Log ----------------------------------------------------------------- commit ffe244ab59c464283ac1833e13377782bee1c122 Author: Mason S <mas...@ma...> Date: Tue Jun 1 17:05:56 2010 -0400 Support for pg_dump and pg_restore. The CREATE TABLE command generation now includes distribution information. Written by Michael Paquier diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index fdb9564..ec86c18 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -3187,6 +3187,10 @@ getTables(int *numTables) int i_relfrozenxid; int i_owning_tab; int i_owning_col; +#ifdef PGXC + int i_pgxclocatortype; + int i_pgxcattnum; +#endif int i_reltablespace; int i_reloptions; int i_toastreloptions; @@ -3219,6 +3223,8 @@ getTables(int *numTables) /* * Left join to pick up dependency info linking sequences to their * owning column, if any (note this dependency is AUTO as of 8.2) + * PGXC is based on PostgreSQL version 8.4, it is not necessary to + * to modify the other SQL queries. */ appendPQExpBuffer(query, "SELECT c.tableoid, c.oid, c.relname, " @@ -3230,7 +3236,11 @@ getTables(int *numTables) "d.refobjid AS owning_tab, " "d.refobjsubid AS owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " - "array_to_string(c.reloptions, ', ') AS reloptions, " +#ifdef PGXC + "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," + "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," +#endif + "array_to_string(c.reloptions, ', ') AS reloptions, " "array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions " "FROM pg_class c " "LEFT JOIN pg_depend d ON " @@ -3448,6 +3458,10 @@ getTables(int *numTables) i_relfrozenxid = PQfnumber(res, "relfrozenxid"); i_owning_tab = PQfnumber(res, "owning_tab"); i_owning_col = PQfnumber(res, "owning_col"); +#ifdef PGXC + i_pgxclocatortype = PQfnumber(res, "pgxclocatortype"); + i_pgxcattnum = PQfnumber(res, "pgxcattnum"); +#endif i_reltablespace = PQfnumber(res, "reltablespace"); i_reloptions = PQfnumber(res, "reloptions"); i_toastreloptions = PQfnumber(res, "toast_reloptions"); @@ -3495,6 +3509,19 @@ getTables(int *numTables) tblinfo[i].owning_tab = atooid(PQgetvalue(res, i, i_owning_tab)); tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col)); } +#ifdef PGXC + /* Not all the tables have pgxc locator Data */ + if (PQgetisnull(res, i, i_pgxclocatortype)) + { + tblinfo[i].pgxclocatortype = 'E'; + tblinfo[i].pgxcattnum = 0; + } + else + { + tblinfo[i].pgxclocatortype = *(PQgetvalue(res, i, i_pgxclocatortype)); + tblinfo[i].pgxcattnum = atoi(PQgetvalue(res, i, i_pgxcattnum)); + } +#endif tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace)); tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions)); tblinfo[i].toast_reloptions = strdup(PQgetvalue(res, i, i_toastreloptions)); @@ -9939,6 +9966,30 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) appendPQExpBuffer(q, ")"); } +#ifdef PGXC + /* Add the grammar extension linked to PGXC depending on data got from pgxc_class */ + if (tbinfo->pgxclocatortype != 'E') + { + /* N: DISTRIBUTE BY ROUND ROBIN */ + if (tbinfo->pgxclocatortype == 'N') + { + appendPQExpBuffer(q, "\nDISTRIBUTE BY ROUND ROBIN"); + } + /* R: DISTRIBUTE BY REPLICATED */ + else if (tbinfo->pgxclocatortype == 'R') + { + appendPQExpBuffer(q, "\nDISTRIBUTE BY REPLICATION"); + } + /* H: DISTRIBUTE BY HASH */ + else if (tbinfo->pgxclocatortype == 'H') + { + int hashkey = tbinfo->pgxcattnum; + appendPQExpBuffer(q, "\nDISTRIBUTE BY HASH (%s)", + fmtId(tbinfo->attnames[hashkey - 1])); + } + } +#endif + appendPQExpBuffer(q, ";\n"); /* diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index a9b3dae..276a3d6 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -16,6 +16,10 @@ #include "postgres_fe.h" +#ifdef PGXC +#include "pgxc/pgxc.h" +#endif + /* * pg_dump uses two different mechanisms for identifying database objects: * @@ -234,6 +238,11 @@ typedef struct _tableInfo bool interesting; /* true if need to collect more data */ +#ifdef PGXC + /* PGXC table locator Data */ + char pgxclocatortype; /* Type of PGXC table locator */ + int pgxcattnum; /* Number of the attribute the table is partitioned with */ +#endif /* * These fields are computed only if we decide the table is interesting * (it's either a table to dump, or a direct parent of a dumpable table). ----------------------------------------------------------------------- Summary of changes: src/bin/pg_dump/pg_dump.c | 53 ++++++++++++++++++++++++++++++++++++++++++++- src/bin/pg_dump/pg_dump.h | 9 +++++++ 2 files changed, 61 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: mason_s <ma...@us...> - 2010-06-01 20:14:49
|
Project "Postgres-XC". The branch, master has been updated via 63b0858e76a740e6b0a5e30fa27d7b1d761ac6af (commit) from 7b0d97791bdd0483e4ec9fe4079f494b76523b25 (commit) - Log ----------------------------------------------------------------- commit 63b0858e76a740e6b0a5e30fa27d7b1d761ac6af Author: Mason S <mas...@ma...> Date: Tue Jun 1 16:04:43 2010 -0400 Add support for immutable stored functions and enable support for many other DDL commands (some of which also depend on stored functions), like CREATE OPERATOR. Written by Michael Paquier diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index f0989bf..b1349de 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -875,6 +875,17 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString) interpret_AS_clause(languageOid, languageName, funcname, as_clause, &prosrc_str, &probin_str); +#ifdef PGXC + /* + * For the time being, only immutable functions are allowed to be created + * for a user. A superuser can create volatile and stable functions freely. + */ + if (volatility != PROVOLATILE_IMMUTABLE && !superuser()) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("stable and volatile not yet supported, function volatility has to be immutable"))); +#endif + /* * Set default values for COST and ROWS depending on other parameters; * reject ROWS if it's not returnsSet. NB: pg_dump knows these default diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index ffb2631..13a0f8b 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -1373,8 +1373,6 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) break; /* Statements that we only want to execute on the Coordinator */ - case T_AlterSeqStmt: - case T_CommentStmt: case T_CreateSeqStmt: case T_VariableShowStmt: query_plan->exec_loc_type = EXEC_ON_COORD; @@ -1400,26 +1398,104 @@ 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 + * all other queries are executed on both Coordinator and Datanode + * On the same point, assert also is not supported + */ + if (((DropPropertyStmt *)parsetree)->removeType == OBJECT_TRIGGER) + ereport(ERROR, + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), + (errmsg("This command is not yet supported.")))); + else + query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; + break; /* * Statements that we execute on both the Coordinator and Data Nodes */ - case T_AlterTableStmt: case T_AlterDatabaseStmt: case T_AlterDatabaseSetStmt: case T_AlterDomainStmt: - case T_AlterObjectSchemaStmt: + case T_AlterFdwStmt: + case T_AlterForeignServerStmt: + case T_AlterFunctionStmt: + case T_AlterOpFamilyStmt: + case T_AlterTSConfigurationStmt: + case T_AlterTSDictionaryStmt: + case T_ClosePortalStmt: /* In case CLOSE ALL is issued */ + case T_CompositeTypeStmt: case T_ConstraintsSetStmt: + case T_CreateCastStmt: + case T_CreateConversionStmt: case T_CreateDomainStmt: case T_CreateEnumStmt: + case T_CreateFdwStmt: + case T_CreateForeignServerStmt: + case T_CreateFunctionStmt: /* Only global functions are supported */ + case T_CreateOpClassStmt: + case T_CreateOpFamilyStmt: + case T_CreatePLangStmt: case T_CreateStmt: case T_CreateSchemaStmt: case T_DeallocateStmt: /* Allow for DEALLOCATE ALL */ case T_DiscardStmt: + case T_DropCastStmt: + case T_DropFdwStmt: + case T_DropForeignServerStmt: + case T_DropPLangStmt: case T_IndexStmt: case T_LockStmt: case T_ReindexStmt: - case T_RenameStmt: + case T_RemoveFuncStmt: + case T_RemoveOpClassStmt: + case T_RemoveOpFamilyStmt: case T_TruncateStmt: case T_VariableSetStmt: @@ -1431,15 +1507,18 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) case T_GrantRoleStmt: case T_CreateRoleStmt: case T_AlterRoleStmt: + case T_AlterRoleSetStmt: + case T_AlterUserMappingStmt: + case T_CreateUserMappingStmt: case T_DropRoleStmt: case T_AlterOwnerStmt: case T_DropOwnedStmt: + case T_DropUserMappingStmt: case T_ReassignOwnedStmt: case T_DefineStmt: /* used for aggregates, some types */ query_plan->exec_loc_type = EXEC_ON_COORD | EXEC_ON_DATA_NODES; break; - case T_TransactionStmt: switch (((TransactionStmt *) parsetree)->kind) { @@ -1463,52 +1542,43 @@ GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list) * data node will do */ case T_ExplainStmt: + 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; query_plan->exec_loc_type = EXEC_ON_DATA_NODES; break; /* - * Statements we do not yet want to handle. + * Trigger queries are not yet supported by PGXC. + * Tablespace queries are also not yet supported. + * Two nodes on the same servers cannot use the same tablespace. + */ + case T_CreateTableSpaceStmt: + case T_CreateTrigStmt: + case T_DropTableSpaceStmt: + ereport(ERROR, + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), + (errmsg("This command is not yet supported.")))); + break; + + /* + * Other statements we do not yet want to handle. * By default they would be fobidden, but we list these for reference. * Note that there is not a 1-1 correspndence between * SQL command and the T_*Stmt structures. */ - case T_AlterFdwStmt: - case T_AlterForeignServerStmt: - case T_AlterFunctionStmt: - case T_AlterOpFamilyStmt: - case T_AlterTSConfigurationStmt: - case T_AlterTSDictionaryStmt: - case T_AlterUserMappingStmt: - case T_ClosePortalStmt: - case T_CompositeTypeStmt: - case T_CreateCastStmt: - case T_CreateConversionStmt: - case T_CreateFdwStmt: - case T_CreateFunctionStmt: - case T_CreateForeignServerStmt: - case T_CreateOpClassStmt: - case T_CreateOpFamilyStmt: - case T_CreatePLangStmt: - case T_CreateTableSpaceStmt: - case T_CreateTrigStmt: - case T_CreateUserMappingStmt: case T_DeclareCursorStmt: - case T_DropCastStmt: - case T_DropFdwStmt: - case T_DropForeignServerStmt: - case T_DropPLangStmt: - case T_DropPropertyStmt: - case T_DropTableSpaceStmt: case T_ExecuteStmt: case T_FetchStmt: case T_ListenStmt: case T_LoadStmt: case T_NotifyStmt: case T_PrepareStmt: - case T_RemoveFuncStmt: - case T_RemoveOpClassStmt: - case T_RemoveOpFamilyStmt: case T_RuleStmt: case T_UnlistenStmt: case T_ViewStmt: ----------------------------------------------------------------------- Summary of changes: src/backend/commands/functioncmds.c | 11 +++ src/backend/pgxc/plan/planner.c | 142 ++++++++++++++++++++++++++--------- 2 files changed, 117 insertions(+), 36 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-28 00:19:26
|
Project "Postgres-XC". The branch, master has been created at 54529d7ad914e2959d7243055bbec08302c7e8dc (commit) - Log ----------------------------------------------------------------- commit 54529d7ad914e2959d7243055bbec08302c7e8dc Author: Mason S <mas...@ma...> Date: Wed May 26 14:08:02 2010 -0400 Minor change that updates COPY so that it knows ahead of time whether or not it should only execute on the Coordinator (pg_catalog tables). Written by Michael Paquier diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 0fd4cb9..d641df8 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -800,6 +800,32 @@ CopyQuoteIdentifier(StringInfo query_buf, char *value) } #endif +#ifdef PGXC +/* + * In case there is no locator info available, copy to/from is launched in portal on coordinator. + * This happens for pg_catalog tables (not user defined ones) + * such as pg_catalog, pg_attribute, etc. + * This part is launched before the portal is activated, so check a first time if there + * some locator data for this relid and if no, return and launch the portal. + */ +bool +IsCoordPortalCopy(const CopyStmt *stmt) +{ + RelationLocInfo *rel_loc; /* the locator key */ + + /* In the case of a COPY SELECT, this is launched on datanodes */ + if(!stmt->relation) + return false; + + rel_loc = GetRelationLocInfo(RangeVarGetRelid(stmt->relation, true)); + + if (!rel_loc) + return true; + + return false; +} +#endif + /* * DoCopy executes the SQL COPY statement * @@ -832,7 +858,7 @@ CopyQuoteIdentifier(StringInfo query_buf, char *value) */ uint64 #ifdef PGXC -DoCopy(const CopyStmt *stmt, const char *queryString, bool exec_on_coord_portal, bool *executed) +DoCopy(const CopyStmt *stmt, const char *queryString, bool exec_on_coord_portal) #else DoCopy(const CopyStmt *stmt, const char *queryString) #endif @@ -1155,21 +1181,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString) exec_nodes = (Exec_Nodes *) palloc0(sizeof(Exec_Nodes)); cstate->rel_loc = GetRelationLocInfo(RelationGetRelid(cstate->rel)); - /* - * In case there is no locator info available, copy to/from is launched in portal on coordinator. - * This happens for pg_catalog tables (not user defined ones) - * such as pg_catalog, pg_attribute, etc. - * This part is launched before the portal is activated, so check a first time if there - * some locator data for this relid and if no, return and launch the portal. - */ - if (!cstate->rel_loc && !exec_on_coord_portal) - { - /* close lock before leaving */ - if (cstate->rel) - heap_close(cstate->rel, (is_from ? NoLock : AccessShareLock)); - *executed = false; - return 0; - } if (exec_on_coord_portal) cstate->on_coord = true; @@ -1552,9 +1563,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString) pfree(cstate->raw_buf); pfree(cstate); -#ifdef PGXC - *executed = true; -#endif return processed; } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index cce476d..a0c0d90 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -992,17 +992,18 @@ exec_simple_query(const char *query_string) /* * A check on locator is made in DoCopy to determine if the copy can be launched on * Datanode or on Coordinator. - * If a table has no locator data, then done is set to false and copy is launched + * If a table has no locator data, then IsCoordPortalCopy returns false and copy is launched * on Coordinator instead (e.g., using pg_catalog tables). - * If a table has some locator data (user tables), then copy was launched normally + * If a table has some locator data (user tables), then copy is launched normally * in Datanodes */ - DoCopy(copy, query_string, false, &done); - - if (!done) - exec_on_coord = true; - else + if (!IsCoordPortalCopy(copy)) + { + DoCopy(copy, query_string, false); exec_on_coord = false; + } + else + exec_on_coord = true; } else { diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index b6275d9..6965e2e 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -602,7 +602,7 @@ ProcessUtility(Node *parsetree, uint64 processed; #ifdef PGXC bool done; - processed = DoCopy((CopyStmt *) parsetree, queryString, true, &done); + processed = DoCopy((CopyStmt *) parsetree, queryString, true); #else processed = DoCopy((CopyStmt *) parsetree, queryString): #endif diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h index 7c0b4ca..5e7830a 100644 --- a/src/include/commands/copy.h +++ b/src/include/commands/copy.h @@ -18,7 +18,8 @@ #include "tcop/dest.h" #ifdef PGXC -extern uint64 DoCopy(const CopyStmt *stmt, const char *queryString, bool exec_on_coord_portal, bool *executed); +extern uint64 DoCopy(const CopyStmt *stmt, const char *queryString, bool exec_on_coord_portal); +extern bool IsCoordPortalCopy(const CopyStmt *stmt); #else extern uint64 DoCopy(const CopyStmt *stmt, const char *queryString); #endif commit 45617c6321fa7a95d0b062f0918c9d9935f7fe53 Author: Mason S <masonsharp@mason-sharps-macbook.local> Date: Wed May 19 19:06:10 2010 -0400 Fixed a bug when using a table after it had been created in the same transaction but not committed. The problem was the location info in relcache was not read in. I just invalidated the entry immediately after creation to force it to be created properly. diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f74c05c..fa6456a 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -547,6 +547,8 @@ DefineRelation(CreateStmt *stmt, char relkind) { AddRelationDistribution (relationId, stmt->distributeby, inheritOids, descriptor); CommandCounterIncrement(); + /* Make sure locator info gets rebuilt */ + RelationCacheInvalidateEntry(relationId); } #endif ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-28 00:18:46
|
Project "Postgres-XC". The branch, master has been deleted was 82fce875e77dbedc7fef0fd0e85c52fd93bca581 ----------------------------------------------------------------------- 82fce875e77dbedc7fef0fd0e85c52fd93bca581 Merge branch 'master' of ssh://mic...@po.../gitroot/postgres-xc/postgres-xc ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: mason_s <ma...@us...> - 2010-05-26 18:09:07
|
Project "Postgres-XC". The branch, master has been updated via 54529d7ad914e2959d7243055bbec08302c7e8dc (commit) from 45617c6321fa7a95d0b062f0918c9d9935f7fe53 (commit) - Log ----------------------------------------------------------------- commit 54529d7ad914e2959d7243055bbec08302c7e8dc Author: Mason S <mas...@ma...> Date: Wed May 26 14:08:02 2010 -0400 Minor change that updates COPY so that it knows ahead of time whether or not it should only execute on the Coordinator (pg_catalog tables). Written by Michael Paquier diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 0fd4cb9..d641df8 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -800,6 +800,32 @@ CopyQuoteIdentifier(StringInfo query_buf, char *value) } #endif +#ifdef PGXC +/* + * In case there is no locator info available, copy to/from is launched in portal on coordinator. + * This happens for pg_catalog tables (not user defined ones) + * such as pg_catalog, pg_attribute, etc. + * This part is launched before the portal is activated, so check a first time if there + * some locator data for this relid and if no, return and launch the portal. + */ +bool +IsCoordPortalCopy(const CopyStmt *stmt) +{ + RelationLocInfo *rel_loc; /* the locator key */ + + /* In the case of a COPY SELECT, this is launched on datanodes */ + if(!stmt->relation) + return false; + + rel_loc = GetRelationLocInfo(RangeVarGetRelid(stmt->relation, true)); + + if (!rel_loc) + return true; + + return false; +} +#endif + /* * DoCopy executes the SQL COPY statement * @@ -832,7 +858,7 @@ CopyQuoteIdentifier(StringInfo query_buf, char *value) */ uint64 #ifdef PGXC -DoCopy(const CopyStmt *stmt, const char *queryString, bool exec_on_coord_portal, bool *executed) +DoCopy(const CopyStmt *stmt, const char *queryString, bool exec_on_coord_portal) #else DoCopy(const CopyStmt *stmt, const char *queryString) #endif @@ -1155,21 +1181,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString) exec_nodes = (Exec_Nodes *) palloc0(sizeof(Exec_Nodes)); cstate->rel_loc = GetRelationLocInfo(RelationGetRelid(cstate->rel)); - /* - * In case there is no locator info available, copy to/from is launched in portal on coordinator. - * This happens for pg_catalog tables (not user defined ones) - * such as pg_catalog, pg_attribute, etc. - * This part is launched before the portal is activated, so check a first time if there - * some locator data for this relid and if no, return and launch the portal. - */ - if (!cstate->rel_loc && !exec_on_coord_portal) - { - /* close lock before leaving */ - if (cstate->rel) - heap_close(cstate->rel, (is_from ? NoLock : AccessShareLock)); - *executed = false; - return 0; - } if (exec_on_coord_portal) cstate->on_coord = true; @@ -1552,9 +1563,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString) pfree(cstate->raw_buf); pfree(cstate); -#ifdef PGXC - *executed = true; -#endif return processed; } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index cce476d..a0c0d90 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -992,17 +992,18 @@ exec_simple_query(const char *query_string) /* * A check on locator is made in DoCopy to determine if the copy can be launched on * Datanode or on Coordinator. - * If a table has no locator data, then done is set to false and copy is launched + * If a table has no locator data, then IsCoordPortalCopy returns false and copy is launched * on Coordinator instead (e.g., using pg_catalog tables). - * If a table has some locator data (user tables), then copy was launched normally + * If a table has some locator data (user tables), then copy is launched normally * in Datanodes */ - DoCopy(copy, query_string, false, &done); - - if (!done) - exec_on_coord = true; - else + if (!IsCoordPortalCopy(copy)) + { + DoCopy(copy, query_string, false); exec_on_coord = false; + } + else + exec_on_coord = true; } else { diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index b6275d9..6965e2e 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -602,7 +602,7 @@ ProcessUtility(Node *parsetree, uint64 processed; #ifdef PGXC bool done; - processed = DoCopy((CopyStmt *) parsetree, queryString, true, &done); + processed = DoCopy((CopyStmt *) parsetree, queryString, true); #else processed = DoCopy((CopyStmt *) parsetree, queryString): #endif diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h index 7c0b4ca..5e7830a 100644 --- a/src/include/commands/copy.h +++ b/src/include/commands/copy.h @@ -18,7 +18,8 @@ #include "tcop/dest.h" #ifdef PGXC -extern uint64 DoCopy(const CopyStmt *stmt, const char *queryString, bool exec_on_coord_portal, bool *executed); +extern uint64 DoCopy(const CopyStmt *stmt, const char *queryString, bool exec_on_coord_portal); +extern bool IsCoordPortalCopy(const CopyStmt *stmt); #else extern uint64 DoCopy(const CopyStmt *stmt, const char *queryString); #endif ----------------------------------------------------------------------- Summary of changes: src/backend/commands/copy.c | 46 +++++++++++++++++++++++++----------------- src/backend/tcop/postgres.c | 15 +++++++------ src/backend/tcop/utility.c | 2 +- src/include/commands/copy.h | 3 +- 4 files changed, 38 insertions(+), 28 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-23 23:52:13
|
Project "website". The branch, master has been updated via 98c2cb0275e1213b44aca6747efa4939e5bd2004 (commit) from 7ddd0345092b7ce4716df4eae1b87e04816064ba (commit) - Log ----------------------------------------------------------------- commit 98c2cb0275e1213b44aca6747efa4939e5bd2004 Author: Michael P <mic...@us...> Date: Mon May 24 08:53:28 2010 +0900 Remove the announce about upcoming PGCon event diff --git a/events.html b/events.html index d36ddb3..52fee74 100755 --- a/events.html +++ b/events.html @@ -12,17 +12,6 @@ ==== UPCOMING EVENTS ==== --> <h2 class="plain">Events</h2> -<!-- PGCon2010 --> -<p class="plain"> -Mar.21, 2010, Postgres-XC -<a href="http://www.pgcon.org/2010/schedule/events/226.en.html" target="_blank"> -presentation -</a> -in -<a href="http://www.pgcon.org/2010/" target="_blank"> -PGCon2010. -</a> -</p> <!-- CHAR(10) --> <p class="plain"> Jul.1 to 3, 2010, ----------------------------------------------------------------------- Summary of changes: events.html | 11 ----------- 1 files changed, 0 insertions(+), 11 deletions(-) hooks/post-receive -- website |
From: Michael P <mic...@us...> - 2010-05-19 23:52:14
|
Project "website". The branch, master has been updated via 7ddd0345092b7ce4716df4eae1b87e04816064ba (commit) via a1153b0635a8949291ae0074d1d517d26bd87b84 (commit) from 2123998b130d93df911f3637680375b26b70d47f (commit) - Log ----------------------------------------------------------------- commit 7ddd0345092b7ce4716df4eae1b87e04816064ba Author: Michael P <mic...@us...> Date: Thu May 20 08:53:06 2010 +0900 Addition of Piwik tags to keep a trace on the website visitors diff --git a/index.html b/index.html index fd3287c..1e8ba9c 100755 --- a/index.html +++ b/index.html @@ -47,4 +47,18 @@ src="events.html" marginheight="10" marginwidth="10" frameborder="0"> </frameset> </frameset> +<body> +<!-- Piwik --> +<script type="text/javascript"> +var pkBaseURL = (("https:" == document.location.protocol) ? "https://sourceforge.net/apps/piwik/postgres-xc/" : "http://sourceforge.net/apps/piwik/postgres-xc/"); +document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E")); +</script><script type="text/javascript"> +try { +var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 1); +piwikTracker.trackPageView(); +piwikTracker.enableLinkTracking(); +} catch( err ) {} +</script><noscript><p><img src="http://sourceforge.net/apps/piwik/postgres-xc/piwik.php?idsite=1" style="border:0" alt=""/></p></noscript> +<!-- End Piwik Tag --> +</body> </html> diff --git a/intro.html b/intro.html index 30a9a0d..2377d1e 100755 --- a/intro.html +++ b/intro.html @@ -71,7 +71,19 @@ to servers containing the target data. <!-- === Overview of the whole system === --> <p class="plain"> <img src="image/arch.jpg" width="650"> -</p> +</p> +<!-- Piwik --> +<script type="text/javascript"> +var pkBaseURL = (("https:" == document.location.protocol) ? "https://sourceforge.net/apps/piwik/postgres-xc/" : "http://sourceforge.net/apps/piwik/postgres-xc/"); +document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E")); +</script><script type="text/javascript"> +try { +var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 1); +piwikTracker.trackPageView(); +piwikTracker.enableLinkTracking(); +} catch( err ) {} +</script><noscript><p><img src="http://sourceforge.net/apps/piwik/postgres-xc/piwik.php?idsite=1" style="border:0" alt=""/></p></noscript> +<!-- End Piwik Tag --> </body> </html> commit a1153b0635a8949291ae0074d1d517d26bd87b84 Author: Michael P <mic...@us...> Date: Wed May 19 14:51:04 2010 +0900 Delete base repository, this leaded in problems with IE7 diff --git a/intro.html b/intro.html index a913d60..30a9a0d 100755 --- a/intro.html +++ b/intro.html @@ -6,7 +6,6 @@ <html lang="en"> <head> <title>Postgres_XC Project Home</title> -<base href="."/> <link rel="stylesheet" type="text/css" href="pgcx_1.css"> </head> <body bgcolor=#FFFFFF> @@ -71,7 +70,7 @@ to servers containing the target data. </p> <!-- === Overview of the whole system === --> <p class="plain"> -<img src="http://postgres-xc.sourceforge.net/image/arch.jpg" width="650"> +<img src="image/arch.jpg" width="650"> </p> </body> </html> diff --git a/scalability.html b/scalability.html index 0b16261..323f460 100755 --- a/scalability.html +++ b/scalability.html @@ -15,7 +15,6 @@ architecture document or be in separate material such as here? <meta name="description" content="Postgres-XC project home"> <meta name="keywords" content="PostgreSQL cluster scalability multi-master"> -<base href="."/> <link rel="stylesheet" type="text/css" href="pgcx_1.css"> </head> <body bgcolor=#FFFFFF> @@ -50,7 +49,7 @@ please refer to the architecture document. The following figure shows Postgres-XC's scalability via number of servers. Dotted line shows ideal scalability. <div align="center"> -<img src="http://postgres-xc.sourceforge.net/image/scalability.jpg" > +<img src="image/scalability.jpg" > </div> </p> </body> ----------------------------------------------------------------------- Summary of changes: index.html | 14 ++++++++++++++ intro.html | 17 ++++++++++++++--- scalability.html | 3 +-- 3 files changed, 29 insertions(+), 5 deletions(-) hooks/post-receive -- website |
From: mason_s <ma...@us...> - 2010-05-19 23:24:54
|
Project "Postgres-XC". The branch, master has been updated via 45617c6321fa7a95d0b062f0918c9d9935f7fe53 (commit) from c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 (commit) - Log ----------------------------------------------------------------- commit 45617c6321fa7a95d0b062f0918c9d9935f7fe53 Author: Mason S <masonsharp@mason-sharps-macbook.local> Date: Wed May 19 19:06:10 2010 -0400 Fixed a bug when using a table after it had been created in the same transaction but not committed. The problem was the location info in relcache was not read in. I just invalidated the entry immediately after creation to force it to be created properly. diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f74c05c..fa6456a 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -547,6 +547,8 @@ DefineRelation(CreateStmt *stmt, char relkind) { AddRelationDistribution (relationId, stmt->distributeby, inheritOids, descriptor); CommandCounterIncrement(); + /* Make sure locator info gets rebuilt */ + RelationCacheInvalidateEntry(relationId); } #endif ----------------------------------------------------------------------- Summary of changes: src/backend/commands/tablecmds.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-19 05:06:51
|
Project "website". The branch, master has been updated via 2123998b130d93df911f3637680375b26b70d47f (commit) from a054fe182f0d61e31b01578c73f23375c3783290 (commit) - Log ----------------------------------------------------------------- commit 2123998b130d93df911f3637680375b26b70d47f Author: Michael P <mic...@us...> Date: Wed May 19 14:07:38 2010 +0900 Modification due to IE7, some jpg images didn't display correctly. diff --git a/intro.html b/intro.html index 6eb0a93..a913d60 100755 --- a/intro.html +++ b/intro.html @@ -71,7 +71,7 @@ to servers containing the target data. </p> <!-- === Overview of the whole system === --> <p class="plain"> -<img src="image/arch.jpg" width="650"> +<img src="http://postgres-xc.sourceforge.net/image/arch.jpg" width="650"> </p> </body> </html> diff --git a/scalability.html b/scalability.html index d07dc81..0b16261 100755 --- a/scalability.html +++ b/scalability.html @@ -50,7 +50,7 @@ please refer to the architecture document. The following figure shows Postgres-XC's scalability via number of servers. Dotted line shows ideal scalability. <div align="center"> -<img src="image/scalability.jpg" > +<img src="http://postgres-xc.sourceforge.net/image/scalability.jpg" > </div> </p> </body> ----------------------------------------------------------------------- Summary of changes: intro.html | 2 +- scalability.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- website |
From: Michael P <mic...@us...> - 2010-05-19 04:00:56
|
Project "website". The branch, master has been updated via a054fe182f0d61e31b01578c73f23375c3783290 (commit) from f6ad2e9ff62f810f539e82929f0eed9947198fa9 (commit) - Log ----------------------------------------------------------------- commit a054fe182f0d61e31b01578c73f23375c3783290 Author: Michael P <mic...@us...> Date: Wed May 19 13:01:29 2010 +0900 Replace the banner on the top so as not to stick with the menu bar. Some Typo corrections diff --git a/index.html b/index.html index 0b1e854..fd3287c 100755 --- a/index.html +++ b/index.html @@ -24,10 +24,10 @@ --> <title>Postgres-XC project Page</title> </head> -<frameset rows=80,1,40,*> +<frameset rows=150,1,40,*> <!-- Title --> <frame name="title" - src="title.html" marginheight="0" marginwidth="0" frameborder="0" + src="title.html" marginheight="25" marginwidth="0" frameborder="0" style = "background-color:#FFFFFF"> <!-- Dummy --> <frame diff --git a/roadmap.html b/roadmap.html index 463b63f..8299fbd 100755 --- a/roadmap.html +++ b/roadmap.html @@ -59,7 +59,7 @@ Version 1.0 (Late in July, 2010) <p class="inner"> <code>ORDER BY</code><br> <code>DISTINCT</code><br> -Stured functions<br> +Stored functions<br> subqueries<br> Views<br> Rules<br> ----------------------------------------------------------------------- Summary of changes: index.html | 4 ++-- roadmap.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) hooks/post-receive -- website |
From: Michael P <mic...@us...> - 2010-05-19 02:50:05
|
Project "Postgres-XC". The branch, REL0_9_1_BETA has been deleted was c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 ----------------------------------------------------------------------- c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 Fix assertion failure so that \d commands with psql work. ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-19 02:45:20
|
Project "website". The branch, master has been updated via f6ad2e9ff62f810f539e82929f0eed9947198fa9 (commit) from 876f53b7c4f395d23930c76d004c7a4fa0b6d6ca (commit) - Log ----------------------------------------------------------------- commit f6ad2e9ff62f810f539e82929f0eed9947198fa9 Author: Michael P <mic...@us...> Date: Wed May 19 11:46:26 2010 +0900 Insert a title to the webpage diff --git a/index.html b/index.html index e1ca6dd..0b1e854 100755 --- a/index.html +++ b/index.html @@ -22,6 +22,7 @@ <!-- Header --- Ends here --> +<title>Postgres-XC project Page</title> </head> <frameset rows=80,1,40,*> <!-- Title --> ----------------------------------------------------------------------- Summary of changes: index.html | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) hooks/post-receive -- website |
From: Michael P <mic...@us...> - 2010-05-19 01:47:55
|
Project "Postgres-XC". The annotated tag, v0.9.1 has been deleted was df6488982d61df01ea012c04bbe45bce3ae11bea ----------------------------------------------------------------------- tag v0.9.1 Postgres-XC version 0.9.1 beta tag c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 Fix assertion failure so that \d commands with psql work. ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-19 00:37:26
|
Project "Postgres-XC". The branch, REL0_9_1_STABLE has been created at c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 (commit) - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-19 00:36:53
|
Project "Postgres-XC". The annotated tag, v0.9.1 has been created at 560b29899b6391982ee819a82794763adbe234a5 (tag) tagging c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 (commit) replaces v0.9 tagged by Michael P on Wed May 19 09:33:18 2010 +0900 - Log ----------------------------------------------------------------- Postgres-XC version 0.9.1 tag Mason S (12): Removed ifdefed code for USE_SSL in GTM, since it is currently For writes to replicated tables, use primary copy technique to reduce Improved error handling. Added support for COPY FROM, for loading tables. Added support for COPY TO a file or STDOUT. Modified pgbench for Postgres-XC. This is the first of some planned changes to recognize more "Postgres-XC safe" Added support for basic aggregate handling. Fixed a bug where if many errors occur we run out of on_proc_exit slots. By default have configure set CFLAGS to use -DPGXC, which is required Fix some assertion failures. Fix assertion failure so that \d commands with psql work. Pavan Deolasee (2): Fix some stylistic issues with the code. Trying to make it more Fix an assertion failure in the GTM code. We were mistakenly overwriting an ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-19 00:11:58
|
Project "Postgres-XC". The branch, REL0_9_1_BETA has been created at c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 (commit) - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-19 00:08:11
|
Project "Postgres-XC". The annotated tag, v0.9.1 has been created at df6488982d61df01ea012c04bbe45bce3ae11bea (tag) tagging c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 (commit) replaces v0.9 tagged by Michael P on Wed May 19 08:56:51 2010 +0900 - Log ----------------------------------------------------------------- Postgres-XC version 0.9.1 beta tag Mason S (12): Removed ifdefed code for USE_SSL in GTM, since it is currently For writes to replicated tables, use primary copy technique to reduce Improved error handling. Added support for COPY FROM, for loading tables. Added support for COPY TO a file or STDOUT. Modified pgbench for Postgres-XC. This is the first of some planned changes to recognize more "Postgres-XC safe" Added support for basic aggregate handling. Fixed a bug where if many errors occur we run out of on_proc_exit slots. By default have configure set CFLAGS to use -DPGXC, which is required Fix some assertion failures. Fix assertion failure so that \d commands with psql work. Pavan Deolasee (2): Fix some stylistic issues with the code. Trying to make it more Fix an assertion failure in the GTM code. We were mistakenly overwriting an ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: mason_s <ma...@us...> - 2010-05-18 22:23:46
|
Project "Postgres-XC". The branch, master has been updated via c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 (commit) from b075a9e103648e81c680e47210e43cbc71b5d958 (commit) - Log ----------------------------------------------------------------- commit c2e5a081606b4dfaaa55e45a76d680b55b6bbc15 Author: Mason S <masonsharp@mason-sharps-macbook.local> Date: Tue May 18 18:22:32 2010 -0400 Fix assertion failure so that \d commands with psql work. Written by Andrei diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index 098cd04..ffb2631 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -274,6 +274,10 @@ get_base_var(Var *var, List *rtables) { RangeTblEntry *rte; + /* Skip system attributes */ + if (!AttrNumberIsForUserDefinedAttr(var->varattno)) + return NULL; + /* get the RangeTableEntry */ rte = list_nth(rtables, var->varno - 1); ----------------------------------------------------------------------- Summary of changes: src/backend/pgxc/plan/planner.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-17 04:57:32
|
Project "DBT-1/Postgres-XC". The annotated tag, pgxc_v0.9.1 has been created at 3ba5e0b47cf390a0e6cbe2579c5393d59e17a41b (tag) tagging 5343ab78653697ec3b01693344d8b4ccc6b5b3b0 (commit) tagged by Michael P on Mon May 17 13:58:45 2010 +0900 - Log ----------------------------------------------------------------- Postgres-XC v0.9.1 Michael P (4): Modified DBT-1 as a benchmark test for Postgres-XC version 0.9 Addition of a README file for user reference DBT-1 update due to the coming release of Postgres-XC 0.9.1. Creation of a new SQL file to upload data directly with COPY FROM. ----------------------------------------------------------------------- hooks/post-receive -- DBT-1/Postgres-XC |
From: Michael P <mic...@us...> - 2010-05-17 04:55:20
|
Project "DBT-1/Postgres-XC". The branch, master has been updated via 5343ab78653697ec3b01693344d8b4ccc6b5b3b0 (commit) from e8423a49d59402dad28ba1499ea3da6fc6289d92 (commit) - Log ----------------------------------------------------------------- commit 5343ab78653697ec3b01693344d8b4ccc6b5b3b0 Author: Michael P <mic...@us...> Date: Mon May 17 13:56:08 2010 +0900 Creation of a new SQL file to upload data directly with COPY FROM. diff --git a/scripts/pgsql/copy.sql b/scripts/pgsql/copy.sql new file mode 100644 index 0000000..595b48a --- /dev/null +++ b/scripts/pgsql/copy.sql @@ -0,0 +1,10 @@ +-- copy dbt1 data to the cluster +copy address from '/tmp/address.data' delimiter '>'; +copy author from '/tmp/author.data' delimiter '>'; +copy stock from '/tmp/stock.data' delimiter '>'; +copy item from '/tmp/item.data' delimiter '>'; +copy country from '/tmp/country.data' delimiter '>'; +copy customer from '/tmp/customer.data' delimiter '>'; +copy orders from '/tmp/orders.data' delimiter '>'; +copy order_line from '/tmp/order_line.data' delimiter '>'; +copy cc_xacts from '/tmp/cc_xacts.data' delimiter '>'; ----------------------------------------------------------------------- Summary of changes: scripts/pgsql/copy.sql | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) create mode 100644 scripts/pgsql/copy.sql hooks/post-receive -- DBT-1/Postgres-XC |