summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/catalog/namespace.c3
-rw-r--r--src/backend/catalog/system_views.sql7
-rw-r--r--src/backend/pgxc/locator/locator.c32
-rw-r--r--src/backend/postmaster/postmaster.c20
-rw-r--r--src/backend/utils/misc/guc.c17
-rw-r--r--src/include/pgxc/locator.h4
-rw-r--r--src/test/regress/expected/prepared_xacts_2.out230
-rw-r--r--src/test/regress/sql/prepared_xacts.sql24
8 files changed, 327 insertions, 10 deletions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index e2e1998550..ee83d37921 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -51,6 +51,9 @@
#include "utils/rel.h"
#include "utils/syscache.h"
+#ifdef PGXC
+#include "pgxc/pgxc.h"
+#endif
/*
* The namespace search path is a possibly-empty list of namespace OIDs.
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 8be3defe75..2edaf48953 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -150,7 +150,12 @@ CREATE VIEW pg_locks AS
CREATE VIEW pg_cursors AS
SELECT * FROM pg_cursor() AS C;
-CREATE VIEW pg_prepared_xacts AS
+CREATE SCHEMA __pgxc_coordinator_schema__;
+CREATE SCHEMA __pgxc_datanode_schema__;
+
+create table __pgxc_coordinator_schema__.pg_prepared_xacts ( transaction xid, gid text, prepared timestamptz, owner name, database name );
+
+CREATE VIEW __pgxc_datanode_schema__.pg_prepared_xacts AS
SELECT P.transaction, P.gid, P.prepared,
U.rolname AS owner, D.datname AS database
FROM pg_prepared_xact() AS P
diff --git a/src/backend/pgxc/locator/locator.c b/src/backend/pgxc/locator/locator.c
index d1aef8b348..4116476fbf 100644
--- a/src/backend/pgxc/locator/locator.c
+++ b/src/backend/pgxc/locator/locator.c
@@ -750,9 +750,41 @@ RelationLocInfo *
GetRelationLocInfo(Oid relid)
{
RelationLocInfo *ret_loc_info = NULL;
+ char *namespace;
Relation rel = relation_open(relid, AccessShareLock);
+ /* This check has been added as a temp fix for CREATE TABLE not adding entry in pgxc_class
+ * when run from system_views.sql
+ */
+ if ( rel != NULL &&
+ rel->rd_rel != NULL &&
+ rel->rd_rel->relkind == RELKIND_RELATION &&
+ rel->rd_rel->relname.data != NULL &&
+ (strcmp(rel->rd_rel->relname.data, PREPARED_XACTS_TABLE) == 0) )
+ {
+ namespace = get_namespace_name(rel->rd_rel->relnamespace);
+
+ if (namespace != NULL && (strcmp(namespace, PGXC_COORDINATOR_SCHEMA) == 0))
+ {
+ RelationLocInfo *dest_info;
+
+ dest_info = (RelationLocInfo *) palloc0(sizeof(RelationLocInfo));
+
+ dest_info->relid = relid;
+ dest_info->locatorType = 'N';
+ dest_info->nodeCount = NumDataNodes;
+ dest_info->nodeList = GetAllDataNodes();
+
+ relation_close(rel, AccessShareLock);
+ pfree(namespace);
+
+ return dest_info;
+ }
+
+ if (namespace != NULL) pfree(namespace);
+ }
+
if (rel && rel->rd_locator_info)
ret_loc_info = CopyRelationLocInfo(rel->rd_locator_info);
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 90f8ff7701..b39dda0f8e 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -538,6 +538,26 @@ PostmasterMain(int argc, char *argv[])
/* Initialize paths to installation files */
getInstallationPaths(argv[0]);
+#ifdef PGXC
+ /* Decide whether coordinator or data node before setting GUC variables */
+ while ((opt = getopt(argc, argv, "A:B:Cc:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:X-:")) != -1)
+ {
+ switch (opt)
+ {
+ case 'C':
+ isPGXCCoordinator = true;
+ break;
+ case 'X':
+ isPGXCDataNode = true;
+ break;
+ default:
+ break;
+ }
+ }
+ /* Reset getopt for parsing again */
+ optind = 1;
+#endif
+
/*
* Options setup
*/
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index c4521fd104..869a172156 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2235,6 +2235,10 @@ static struct config_int ConfigureNamesInt[] =
}
};
+#ifdef PGXC
+/* Variable to store search path */
+static char boot_search_path[255];
+#endif
static struct config_real ConfigureNamesReal[] =
{
@@ -2363,7 +2367,6 @@ static struct config_real ConfigureNamesReal[] =
}
};
-
static struct config_string ConfigureNamesString[] =
{
{
@@ -2560,7 +2563,11 @@ static struct config_string ConfigureNamesString[] =
GUC_LIST_INPUT | GUC_LIST_QUOTE
},
&namespace_search_path,
+#ifdef PGXC
+ boot_search_path, assign_search_path, NULL
+#else
"\"$user\",public", assign_search_path, NULL
+#endif
},
{
@@ -3291,6 +3298,14 @@ build_guc_variables(void)
struct config_generic **guc_vars;
int i;
+#ifdef PGXC
+ strcpy(boot_search_path, "\"$user\",public, ");
+ if (IS_PGXC_DATANODE)
+ strcat(boot_search_path, PGXC_DATA_NODE_SCHEMA);
+ else
+ strcat(boot_search_path, PGXC_COORDINATOR_SCHEMA);
+#endif
+
for (i = 0; ConfigureNamesBool[i].gen.name; i++)
{
struct config_bool *conf = &ConfigureNamesBool[i];
diff --git a/src/include/pgxc/locator.h b/src/include/pgxc/locator.h
index 3272ab6cb1..9f669d92e0 100644
--- a/src/include/pgxc/locator.h
+++ b/src/include/pgxc/locator.h
@@ -28,6 +28,10 @@
#define IsReplicated(x) (x->locatorType == LOCATOR_TYPE_REPLICATED)
+#define PGXC_COORDINATOR_SCHEMA "__pgxc_coordinator_schema__"
+#define PGXC_DATA_NODE_SCHEMA "__pgxc_datanode_schema__"
+#define PREPARED_XACTS_TABLE "pg_prepared_xacts"
+
#include "nodes/primnodes.h"
#include "utils/relcache.h"
diff --git a/src/test/regress/expected/prepared_xacts_2.out b/src/test/regress/expected/prepared_xacts_2.out
new file mode 100644
index 0000000000..e4562001df
--- /dev/null
+++ b/src/test/regress/expected/prepared_xacts_2.out
@@ -0,0 +1,230 @@
+--
+-- PREPARED TRANSACTIONS (two-phase commit)
+--
+-- We can't readily test persistence of prepared xacts within the
+-- regression script framework, unfortunately. Note that a crash
+-- isn't really needed ... stopping and starting the postmaster would
+-- be enough, but we can't even do that here.
+-- create a simple table that we'll use in the tests
+CREATE TABLE pxtest1 (foobar VARCHAR(10));
+INSERT INTO pxtest1 VALUES ('aaa');
+-- Test PREPARE TRANSACTION
+BEGIN;
+UPDATE pxtest1 SET foobar = 'bbb' WHERE foobar = 'aaa';
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ bbb
+(1 row)
+
+PREPARE TRANSACTION 'foo1';
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+(1 row)
+
+-- Test pg_prepared_xacts system view
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
+ gid
+------
+ foo1
+(1 row)
+
+-- Test ROLLBACK PREPARED
+ROLLBACK PREPARED 'foo1';
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+(1 row)
+
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
+ gid
+-----
+(0 rows)
+
+-- Test COMMIT PREPARED
+BEGIN;
+INSERT INTO pxtest1 VALUES ('ddd');
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+ ddd
+(2 rows)
+
+PREPARE TRANSACTION 'foo2';
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+(1 row)
+
+COMMIT PREPARED 'foo2';
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+ ddd
+(2 rows)
+
+-- Test duplicate gids
+BEGIN;
+UPDATE pxtest1 SET foobar = 'eee' WHERE foobar = 'ddd';
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+ eee
+(2 rows)
+
+PREPARE TRANSACTION 'foo3';
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
+ gid
+------
+ foo3
+(1 row)
+
+BEGIN;
+INSERT INTO pxtest1 VALUES ('fff');
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+ ddd
+ fff
+(3 rows)
+
+-- This should fail, because the gid foo3 is already in use
+PREPARE TRANSACTION 'foo3';
+ERROR: Could not prepare transaction on data nodes
+ROLLBACK;
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+ ddd
+(2 rows)
+
+ROLLBACK PREPARED 'foo3';
+SELECT * FROM pxtest1 ORDER BY foobar;
+ foobar
+--------
+ aaa
+ ddd
+(2 rows)
+
+-- Clean up
+DROP TABLE pxtest1;
+-- Test subtransactions
+BEGIN;
+ CREATE TABLE pxtest2 (a int);
+ INSERT INTO pxtest2 VALUES (1);
+ SAVEPOINT a;
+ERROR: SAVEPOINT is not yet supported.
+ INSERT INTO pxtest2 VALUES (2);
+ERROR: current transaction is aborted, commands ignored until end of transaction block
+ ROLLBACK TO a;
+ERROR: no such savepoint
+ SAVEPOINT b;
+ERROR: current transaction is aborted, commands ignored until end of transaction block
+ INSERT INTO pxtest2 VALUES (3);
+ERROR: current transaction is aborted, commands ignored until end of transaction block
+PREPARE TRANSACTION 'regress-one';
+BEGIN;
+ CREATE TABLE pxtest2 (a int);
+ INSERT INTO pxtest2 VALUES (1);
+ INSERT INTO pxtest2 VALUES (3);
+PREPARE TRANSACTION 'regress-one';
+CREATE TABLE pxtest3(fff int);
+-- Test shared invalidation
+BEGIN;
+ DROP TABLE pxtest3;
+ CREATE TABLE pxtest4 (a int);
+ INSERT INTO pxtest4 VALUES (1);
+ INSERT INTO pxtest4 VALUES (2);
+ DECLARE foo CURSOR FOR SELECT * FROM pxtest4;
+ -- Fetch 1 tuple, keeping the cursor open
+ FETCH 1 FROM foo;
+ a
+---
+ 1
+(1 row)
+
+PREPARE TRANSACTION 'regress-two';
+-- No such cursor
+FETCH 1 FROM foo;
+ERROR: cursor "foo" does not exist
+-- Table doesn't exist, the creation hasn't been committed yet
+SELECT * FROM pxtest2;
+ERROR: relation "pxtest2" does not exist
+LINE 1: SELECT * FROM pxtest2;
+ ^
+-- There should be two prepared transactions
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
+ gid
+-------------
+ regress-one
+ regress-two
+(2 rows)
+
+-- pxtest3 should be locked because of the pending DROP
+set statement_timeout to 2000;
+SELECT * FROM pxtest3;
+ERROR: canceling statement due to statement timeout
+reset statement_timeout;
+-- Disconnect, we will continue testing in a different backend
+\c -
+-- There should still be two prepared transactions
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
+ gid
+-------------
+ regress-one
+ regress-two
+(2 rows)
+
+-- pxtest3 should still be locked because of the pending DROP
+set statement_timeout to 2000;
+SELECT * FROM pxtest3;
+ERROR: canceling statement due to statement timeout
+reset statement_timeout;
+-- Commit table creation
+COMMIT PREPARED 'regress-one';
+\d pxtest2
+ Table "public.pxtest2"
+ Column | Type | Modifiers
+--------+---------+-----------
+ a | integer |
+
+SELECT * FROM pxtest2;
+ a
+---
+ 1
+ 3
+(2 rows)
+
+-- There should be one prepared transaction
+SELECT DISTINCT gid FROM pg_prepared_xacts;
+ gid
+-------------
+ regress-two
+(1 row)
+
+-- Commit table drop
+COMMIT PREPARED 'regress-two';
+SELECT * FROM pxtest3;
+ERROR: relation "pxtest3" does not exist
+LINE 1: SELECT * FROM pxtest3;
+ ^
+-- There should be no prepared transactions
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
+ gid
+-----
+(0 rows)
+
+-- Clean up
+DROP TABLE pxtest2;
+DROP TABLE pxtest3; -- will still be there if prepared xacts are disabled
+ERROR: table "pxtest3" does not exist
+DROP TABLE pxtest4;
diff --git a/src/test/regress/sql/prepared_xacts.sql b/src/test/regress/sql/prepared_xacts.sql
index b8915bda77..fb9bc64c8d 100644
--- a/src/test/regress/sql/prepared_xacts.sql
+++ b/src/test/regress/sql/prepared_xacts.sql
@@ -22,14 +22,14 @@ PREPARE TRANSACTION 'foo1';
SELECT * FROM pxtest1 ORDER BY foobar;
-- Test pg_prepared_xacts system view
-SELECT gid FROM pg_prepared_xacts ORDER BY gid;
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
-- Test ROLLBACK PREPARED
ROLLBACK PREPARED 'foo1';
SELECT * FROM pxtest1 ORDER BY foobar;
-SELECT gid FROM pg_prepared_xacts ORDER BY gid;
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
-- Test COMMIT PREPARED
@@ -50,7 +50,7 @@ UPDATE pxtest1 SET foobar = 'eee' WHERE foobar = 'ddd';
SELECT * FROM pxtest1 ORDER BY foobar;
PREPARE TRANSACTION 'foo3';
-SELECT gid FROM pg_prepared_xacts ORDER BY gid;
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
BEGIN;
INSERT INTO pxtest1 VALUES ('fff');
@@ -59,8 +59,8 @@ SELECT * FROM pxtest1 ORDER BY foobar;
-- This should fail, because the gid foo3 is already in use
PREPARE TRANSACTION 'foo3';
+ROLLBACK;
SELECT * FROM pxtest1 ORDER BY foobar;
-
ROLLBACK PREPARED 'foo3';
SELECT * FROM pxtest1 ORDER BY foobar;
@@ -79,6 +79,13 @@ BEGIN;
INSERT INTO pxtest2 VALUES (3);
PREPARE TRANSACTION 'regress-one';
+BEGIN;
+ CREATE TABLE pxtest2 (a int);
+ INSERT INTO pxtest2 VALUES (1);
+ INSERT INTO pxtest2 VALUES (3);
+PREPARE TRANSACTION 'regress-one';
+
+
CREATE TABLE pxtest3(fff int);
-- Test shared invalidation
@@ -99,7 +106,7 @@ FETCH 1 FROM foo;
SELECT * FROM pxtest2;
-- There should be two prepared transactions
-SELECT gid FROM pg_prepared_xacts ORDER BY gid;
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
-- pxtest3 should be locked because of the pending DROP
set statement_timeout to 2000;
@@ -110,7 +117,7 @@ reset statement_timeout;
\c -
-- There should still be two prepared transactions
-SELECT gid FROM pg_prepared_xacts ORDER BY gid;
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
-- pxtest3 should still be locked because of the pending DROP
set statement_timeout to 2000;
@@ -123,16 +130,17 @@ COMMIT PREPARED 'regress-one';
SELECT * FROM pxtest2;
-- There should be one prepared transaction
-SELECT gid FROM pg_prepared_xacts;
+SELECT DISTINCT gid FROM pg_prepared_xacts;
-- Commit table drop
COMMIT PREPARED 'regress-two';
SELECT * FROM pxtest3;
-- There should be no prepared transactions
-SELECT gid FROM pg_prepared_xacts ORDER BY gid;
+SELECT DISTINCT gid FROM pg_prepared_xacts ORDER BY gid;
-- Clean up
DROP TABLE pxtest2;
DROP TABLE pxtest3; -- will still be there if prepared xacts are disabled
DROP TABLE pxtest4;
+