summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier2012-04-29 00:28:23 +0000
committerMichael Paquier2012-04-29 00:28:23 +0000
commit8c579ff58656330512b4e66a89836ae5f3286b90 (patch)
tree7e2d8b18811dcfdba867a53bd615645e41c6c4b3
parenteb356aee558bafed6e2112da117c9eb7f68b1116 (diff)
Callback mechanism on GTM for sequence renaming
Addition of a callback at transaction abort to change a sequence on GTM back to its former name in case it has been changed during this transaction. A new regression test called xc_sequence is added with test cases for sequence creation and drop callback, and renaming callback.
-rw-r--r--src/backend/catalog/dependency.c3
-rw-r--r--src/backend/commands/sequence.c74
-rw-r--r--src/backend/commands/tablecmds.c9
-rw-r--r--src/include/commands/sequence.h5
-rw-r--r--src/test/regress/expected/xc_sequence.out178
-rw-r--r--src/test/regress/parallel_schedule2
-rw-r--r--src/test/regress/serial_schedule1
-rw-r--r--src/test/regress/sql/xc_sequence.sql86
8 files changed, 356 insertions, 2 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 9f6b58f31f..f426ecf118 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -392,6 +392,9 @@ doRename(const ObjectAddress *object, const char *oldname, const char *newname)
(errcode(ERRCODE_CONNECTION_FAILURE),
errmsg("GTM error, could not rename sequence")));
+ /* Register a rename callback in case transaction is dropped */
+ register_sequence_rename_cb(seqname, newseqname);
+
pfree(seqname);
pfree(newseqname);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 7647470113..875399b08f 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -101,6 +101,15 @@ typedef struct drop_sequence_callback_arg
GTM_SequenceDropType type;
GTM_SequenceKeyType key;
} drop_sequence_callback_arg;
+
+/*
+ * Arguments for callback of sequence rename on GTM
+ */
+typedef struct rename_sequence_callback_arg
+{
+ char *newseqname;
+ char *oldseqname;
+} rename_sequence_callback_arg;
#endif
/*
@@ -1902,6 +1911,71 @@ seq_desc(StringInfo buf, uint8 xl_info, char *rec)
#ifdef PGXC
/*
+ * Register a callback for a sequence rename drop on GTM
+ */
+void
+register_sequence_rename_cb(char *oldseqname, char *newseqname)
+{
+ rename_sequence_callback_arg *args;
+ char *oldseqnamearg = NULL;
+ char *newseqnamearg = NULL;
+
+ /* All the arguments are transaction-dependent, so save them in TopTransactionContext */
+ args = (rename_sequence_callback_arg *)
+ MemoryContextAlloc(TopTransactionContext, sizeof(rename_sequence_callback_arg));
+
+ oldseqnamearg = MemoryContextAlloc(TopTransactionContext, strlen(oldseqname) + 1);
+ newseqnamearg = MemoryContextAlloc(TopTransactionContext, strlen(newseqname) + 1);
+ sprintf(oldseqnamearg, "%s", oldseqname);
+ sprintf(newseqnamearg, "%s", newseqname);
+
+ args->oldseqname = oldseqnamearg;
+ args->newseqname = newseqnamearg;
+
+ RegisterGTMCallback(rename_sequence_cb, (void *) args);
+}
+
+/*
+ * Callback a sequence rename
+ */
+void
+rename_sequence_cb(GTMEvent event, void *args)
+{
+ rename_sequence_callback_arg *cbargs = (rename_sequence_callback_arg *) args;
+ char *newseqname = cbargs->newseqname;
+ char *oldseqname = cbargs->oldseqname;
+ int err = 0;
+
+ /*
+ * A sequence is here renamed to its former name only when a transaction
+ * that involved a sequence rename was dropped.
+ */
+ switch (event)
+ {
+ case GTM_EVENT_ABORT:
+ /*
+ * Here sequence is renamed to its former name
+ * so what was new becomes old.
+ */
+ err = RenameSequenceGTM(newseqname, oldseqname);
+ break;
+ case GTM_EVENT_COMMIT:
+ case GTM_EVENT_PREPARE:
+ /* Nothing to do */
+ break;
+ default:
+ Assert(0);
+ }
+
+ /* Report error if necessary */
+ if (err < 0 && event != GTM_EVENT_ABORT)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONNECTION_FAILURE),
+ errmsg("GTM error, could not rename sequence")));
+}
+
+
+/*
* Register a callback for a sequence drop on GTM
*/
void
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index e542f51247..02042e6eb0 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -2311,6 +2311,9 @@ RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
(errcode(ERRCODE_CONNECTION_FAILURE),
errmsg("GTM error, could not rename sequence")));
+ /* Register a rename callback in case transaction is dropped */
+ register_sequence_rename_cb(seqname, newseqname);
+
pfree(seqname);
pfree(newseqname);
}
@@ -9126,6 +9129,9 @@ AlterTableNamespace(RangeVar *relation, const char *newschema,
(errcode(ERRCODE_CONNECTION_FAILURE),
errmsg("GTM error, could not rename sequence")));
+ /* Register a rename callback in case transaction is dropped */
+ register_sequence_rename_cb(seqname, newseqname);
+
pfree(seqname);
pfree(newseqname);
}
@@ -9297,6 +9303,9 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
(errcode(ERRCODE_CONNECTION_FAILURE),
errmsg("GTM error, could not rename sequence")));
+ /* Register a rename callback in case transaction is dropped */
+ register_sequence_rename_cb(seqname, newseqname);
+
pfree(seqname);
pfree(newseqname);
}
diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h
index 84df50e101..f9d45de4af 100644
--- a/src/include/commands/sequence.h
+++ b/src/include/commands/sequence.h
@@ -87,7 +87,8 @@ extern void seq_desc(StringInfo buf, uint8 xl_info, char *rec);
/*
* List of actions that registered the callback.
* This is listed here and not in sequence.c because callback can also
- * be registered in dependency.c as sequences can be dropped in cascade.
+ * be registered in dependency.c and tablecmds.c as sequences can be dropped
+ * or renamed in cascade.
*/
typedef enum
{
@@ -96,6 +97,8 @@ typedef enum
} GTM_SequenceDropType;
/* Sequence callbacks on GTM */
+extern void register_sequence_rename_cb(char *oldseqname, char *newseqname);
+extern void rename_sequence_cb(GTMEvent event, void *args);
extern void register_sequence_cb(char *seqname, GTM_SequenceKeyType key, GTM_SequenceDropType type);
extern void drop_sequence_cb(GTMEvent event, void *args);
diff --git a/src/test/regress/expected/xc_sequence.out b/src/test/regress/expected/xc_sequence.out
new file mode 100644
index 0000000000..6927847757
--- /dev/null
+++ b/src/test/regress/expected/xc_sequence.out
@@ -0,0 +1,178 @@
+--
+-- XC_SEQUENCE
+--
+-- Check of callback mechanisms on GTM
+-- Sequence DROP and CREATE
+-- Rollback a creation
+BEGIN;
+CREATE SEQUENCE xc_sequence_1;
+SELECT nextval('xc_sequence_1'); -- ok
+ nextval
+---------
+ 1
+(1 row)
+
+ROLLBACK;
+SELECT nextval('xc_sequence_1'); -- fail
+ERROR: relation "xc_sequence_1" does not exist
+LINE 1: SELECT nextval('xc_sequence_1');
+ ^
+-- Commit a creation
+BEGIN;
+CREATE SEQUENCE xc_sequence_1;
+SELECT nextval('xc_sequence_1'); -- ok
+ nextval
+---------
+ 1
+(1 row)
+
+COMMIT;
+SELECT nextval('xc_sequence_1'); -- ok
+ nextval
+---------
+ 2
+(1 row)
+
+-- Rollback a drop
+BEGIN;
+DROP SEQUENCE xc_sequence_1;
+SELECT nextval('xc_sequence_1'); -- fail
+ERROR: relation "xc_sequence_1" does not exist
+LINE 1: SELECT nextval('xc_sequence_1');
+ ^
+ROLLBACK;
+SELECT nextval('xc_sequence_1'); -- ok, previous transaction failed
+ nextval
+---------
+ 3
+(1 row)
+
+-- Commit a drop
+BEGIN;
+DROP SEQUENCE xc_sequence_1;
+COMMIT;
+SELECT nextval('xc_sequence_1'); -- fail
+ERROR: relation "xc_sequence_1" does not exist
+LINE 1: SELECT nextval('xc_sequence_1');
+ ^
+-- SEQUENCE RENAME TO
+-- Rollback a renaming
+CREATE SEQUENCE xc_sequence_1;
+SELECT nextval('xc_sequence_1'); -- ok
+ nextval
+---------
+ 1
+(1 row)
+
+BEGIN;
+ALTER SEQUENCE xc_sequence_1 RENAME TO xc_sequence_2;
+SELECT nextval('xc_sequence_2'); -- ok
+ nextval
+---------
+ 2
+(1 row)
+
+ROLLBACK;
+SELECT nextval('xc_sequence_1'); -- ok
+ nextval
+---------
+ 3
+(1 row)
+
+-- Commit a renaming
+BEGIN;
+ALTER SEQUENCE xc_sequence_1 RENAME TO xc_sequence_2;
+SELECT nextval('xc_sequence_2'); -- ok
+ nextval
+---------
+ 4
+(1 row)
+
+COMMIT;
+SELECT nextval('xc_sequence_2'); -- ok
+ nextval
+---------
+ 5
+(1 row)
+
+DROP SEQUENCE xc_sequence_2;
+-- Columns with SERIAL
+-- Serial sequence is named xc_sequence_tab1_col2_seq
+CREATE TABLE xc_sequence_tab1 (col1 int, col2 serial) DISTRIBUTE BY ROUND ROBIN;
+NOTICE: CREATE TABLE will create implicit sequence "xc_sequence_tab1_col2_seq" for serial column "xc_sequence_tab1.col2"
+-- Some data
+INSERT INTO xc_sequence_tab1 VALUES (1, DEFAULT);
+INSERT INTO xc_sequence_tab1 VALUES (2, DEFAULT);
+SELECT col1, col2 FROM xc_sequence_tab1 ORDER BY 1;
+ col1 | col2
+------+------
+ 1 | 1
+ 2 | 2
+(2 rows)
+
+-- Rollback a SERIAL column drop
+BEGIN;
+ALTER TABLE xc_sequence_tab1 DROP COLUMN col2;
+INSERT INTO xc_sequence_tab1 VALUES (3);
+SELECT col1 FROM xc_sequence_tab1 ORDER BY 1;
+ col1
+------
+ 1
+ 2
+ 3
+(3 rows)
+
+ROLLBACK;
+SELECT nextval('xc_sequence_tab1_col2_seq'); -- ok
+ nextval
+---------
+ 3
+(1 row)
+
+-- Commit a SERIAL column drop
+BEGIN;
+ALTER TABLE xc_sequence_tab1 DROP COLUMN col2;
+INSERT INTO xc_sequence_tab1 VALUES (3);
+SELECT col1 FROM xc_sequence_tab1 ORDER BY 1;
+ col1
+------
+ 1
+ 2
+ 3
+(3 rows)
+
+COMMIT;
+DROP TABLE xc_sequence_tab1;
+-- Need to recreate here, serial column is no more
+CREATE TABLE xc_sequence_tab1 (col1 int, col2 serial) DISTRIBUTE BY ROUND ROBIN;
+NOTICE: CREATE TABLE will create implicit sequence "xc_sequence_tab1_col2_seq" for serial column "xc_sequence_tab1.col2"
+INSERT INTO xc_sequence_tab1 VALUES (1234, DEFAULT);
+SELECT col1, col2 FROM xc_sequence_tab1 ORDER BY 1;
+ col1 | col2
+------+------
+ 1234 | 1
+(1 row)
+
+-- Rollback of a table with SERIAL
+BEGIN;
+DROP TABLE xc_sequence_tab1;
+ROLLBACK;
+SELECT nextval('xc_sequence_tab1_col2_seq'); -- ok
+ nextval
+---------
+ 2
+(1 row)
+
+-- Commit of a table with SERIAL
+BEGIN;
+DROP TABLE xc_sequence_tab1;
+COMMIT;
+-- Recreate a sequence with the same name as previous SERIAL one
+CREATE SEQUENCE xc_sequence_tab1_col2_seq START 2344;
+SELECT nextval('xc_sequence_tab1_col2_seq'); -- ok
+ nextval
+---------
+ 2344
+(1 row)
+
+DROP SEQUENCE xc_sequence_tab1_col2_seq;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 8b3f496250..835d483f7f 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -104,7 +104,7 @@ test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid c
test: stats
#Postgres-XC additional tests, they can be run in parallel
-test: xc_groupby xc_distkey xc_having xc_temp xc_remote xc_FQS xc_FQS_join xc_copy xc_for_update xc_alter_table
+test: xc_groupby xc_distkey xc_having xc_temp xc_remote xc_FQS xc_FQS_join xc_copy xc_for_update xc_alter_table xc_sequence
#Cluster setting related test is independant
test: xc_node
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index fe4149ff81..8b4d7f9290 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -139,3 +139,4 @@ test: xc_misc
test: xc_copy
test: xc_for_update
test: xc_alter_table
+test: xc_sequence
diff --git a/src/test/regress/sql/xc_sequence.sql b/src/test/regress/sql/xc_sequence.sql
new file mode 100644
index 0000000000..0c731df967
--- /dev/null
+++ b/src/test/regress/sql/xc_sequence.sql
@@ -0,0 +1,86 @@
+--
+-- XC_SEQUENCE
+--
+
+-- Check of callback mechanisms on GTM
+
+-- Sequence DROP and CREATE
+-- Rollback a creation
+BEGIN;
+CREATE SEQUENCE xc_sequence_1;
+SELECT nextval('xc_sequence_1'); -- ok
+ROLLBACK;
+SELECT nextval('xc_sequence_1'); -- fail
+-- Commit a creation
+BEGIN;
+CREATE SEQUENCE xc_sequence_1;
+SELECT nextval('xc_sequence_1'); -- ok
+COMMIT;
+SELECT nextval('xc_sequence_1'); -- ok
+-- Rollback a drop
+BEGIN;
+DROP SEQUENCE xc_sequence_1;
+SELECT nextval('xc_sequence_1'); -- fail
+ROLLBACK;
+SELECT nextval('xc_sequence_1'); -- ok, previous transaction failed
+-- Commit a drop
+BEGIN;
+DROP SEQUENCE xc_sequence_1;
+COMMIT;
+SELECT nextval('xc_sequence_1'); -- fail
+
+-- SEQUENCE RENAME TO
+-- Rollback a renaming
+CREATE SEQUENCE xc_sequence_1;
+SELECT nextval('xc_sequence_1'); -- ok
+BEGIN;
+ALTER SEQUENCE xc_sequence_1 RENAME TO xc_sequence_2;
+SELECT nextval('xc_sequence_2'); -- ok
+ROLLBACK;
+SELECT nextval('xc_sequence_1'); -- ok
+-- Commit a renaming
+BEGIN;
+ALTER SEQUENCE xc_sequence_1 RENAME TO xc_sequence_2;
+SELECT nextval('xc_sequence_2'); -- ok
+COMMIT;
+SELECT nextval('xc_sequence_2'); -- ok
+DROP SEQUENCE xc_sequence_2;
+
+-- Columns with SERIAL
+-- Serial sequence is named xc_sequence_tab1_col2_seq
+CREATE TABLE xc_sequence_tab1 (col1 int, col2 serial) DISTRIBUTE BY ROUND ROBIN;
+-- Some data
+INSERT INTO xc_sequence_tab1 VALUES (1, DEFAULT);
+INSERT INTO xc_sequence_tab1 VALUES (2, DEFAULT);
+SELECT col1, col2 FROM xc_sequence_tab1 ORDER BY 1;
+-- Rollback a SERIAL column drop
+BEGIN;
+ALTER TABLE xc_sequence_tab1 DROP COLUMN col2;
+INSERT INTO xc_sequence_tab1 VALUES (3);
+SELECT col1 FROM xc_sequence_tab1 ORDER BY 1;
+ROLLBACK;
+SELECT nextval('xc_sequence_tab1_col2_seq'); -- ok
+-- Commit a SERIAL column drop
+BEGIN;
+ALTER TABLE xc_sequence_tab1 DROP COLUMN col2;
+INSERT INTO xc_sequence_tab1 VALUES (3);
+SELECT col1 FROM xc_sequence_tab1 ORDER BY 1;
+COMMIT;
+DROP TABLE xc_sequence_tab1;
+-- Need to recreate here, serial column is no more
+CREATE TABLE xc_sequence_tab1 (col1 int, col2 serial) DISTRIBUTE BY ROUND ROBIN;
+INSERT INTO xc_sequence_tab1 VALUES (1234, DEFAULT);
+SELECT col1, col2 FROM xc_sequence_tab1 ORDER BY 1;
+-- Rollback of a table with SERIAL
+BEGIN;
+DROP TABLE xc_sequence_tab1;
+ROLLBACK;
+SELECT nextval('xc_sequence_tab1_col2_seq'); -- ok
+-- Commit of a table with SERIAL
+BEGIN;
+DROP TABLE xc_sequence_tab1;
+COMMIT;
+-- Recreate a sequence with the same name as previous SERIAL one
+CREATE SEQUENCE xc_sequence_tab1_col2_seq START 2344;
+SELECT nextval('xc_sequence_tab1_col2_seq'); -- ok
+DROP SEQUENCE xc_sequence_tab1_col2_seq;