You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
(4) |
May
(28) |
Jun
(12) |
Jul
(11) |
Aug
(12) |
Sep
(5) |
Oct
(19) |
Nov
(14) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(18) |
Feb
(30) |
Mar
(115) |
Apr
(89) |
May
(50) |
Jun
(44) |
Jul
(22) |
Aug
(13) |
Sep
(11) |
Oct
(30) |
Nov
(28) |
Dec
(39) |
2012 |
Jan
(38) |
Feb
(18) |
Mar
(43) |
Apr
(91) |
May
(108) |
Jun
(46) |
Jul
(37) |
Aug
(44) |
Sep
(33) |
Oct
(29) |
Nov
(36) |
Dec
(15) |
2013 |
Jan
(35) |
Feb
(611) |
Mar
(5) |
Apr
(55) |
May
(30) |
Jun
(28) |
Jul
(458) |
Aug
(34) |
Sep
(9) |
Oct
(39) |
Nov
(22) |
Dec
(32) |
2014 |
Jan
(16) |
Feb
(16) |
Mar
(42) |
Apr
(179) |
May
(7) |
Jun
(6) |
Jul
(9) |
Aug
|
Sep
(4) |
Oct
|
Nov
(3) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
1
(3) |
2
(5) |
3
|
4
(4) |
5
|
6
|
7
(7) |
8
(10) |
9
(6) |
10
(5) |
11
(1) |
12
|
13
|
14
|
15
|
16
|
17
(4) |
18
(1) |
19
|
20
|
21
(5) |
22
(15) |
23
(18) |
24
(7) |
25
(4) |
26
|
27
|
28
(3) |
29
(2) |
30
(11) |
31
(4) |
|
|
From: Michael P. <mic...@us...> - 2011-03-31 16:21:23
|
Project "Postgres-XC". The branch, master has been updated via 0429a889372c6db0b4b1253624601c42410cc108 (commit) from 124814afe8603b4ec933f6f7b0b646a2a36f53cd (commit) - Log ----------------------------------------------------------------- commit 0429a889372c6db0b4b1253624601c42410cc108 Author: Michael P <mic...@us...> Date: Fri Apr 1 00:31:29 2011 +0900 Support for GRANT and REVOKE Spread GRANT and REVOKE to all the nodes of the cluster. diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 284a52c..49c018b 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1008,10 +1008,20 @@ standard_ProcessUtility(Node *parsetree, case T_GrantStmt: ExecuteGrantStmt((GrantStmt *) parsetree); + +#ifdef PGXC + if (IS_PGXC_COORDINATOR) + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); +#endif break; case T_GrantRoleStmt: GrantRole((GrantRoleStmt *) parsetree); + +#ifdef PGXC + if (IS_PGXC_COORDINATOR) + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); +#endif break; case T_AlterDefaultPrivilegesStmt: ----------------------------------------------------------------------- Summary of changes: src/backend/tcop/utility.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-31 10:37:23
|
Project "Postgres-XC". The branch, master has been updated via 124814afe8603b4ec933f6f7b0b646a2a36f53cd (commit) from baa0d2e4589347558b6fd894d431c1ff42151492 (commit) - Log ----------------------------------------------------------------- commit 124814afe8603b4ec933f6f7b0b646a2a36f53cd Author: Michael P <mic...@us...> Date: Thu Mar 31 19:36:40 2011 +0900 Remove debug flag from GTM Makefile diff --git a/src/gtm/Makefile.global b/src/gtm/Makefile.global index 684690b..09c8993 100644 --- a/src/gtm/Makefile.global +++ b/src/gtm/Makefile.global @@ -29,7 +29,7 @@ enable_shared = yes # Compilers CPP = gcc -E -CPPFLAGS = -g -D_GNU_SOURCE +CPPFLAGS = -D_GNU_SOURCE override CPPFLAGS := -I$(top_srcdir)/include $(CPPFLAGS) ----------------------------------------------------------------------- Summary of changes: src/gtm/Makefile.global | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-31 10:32:25
|
Project "Postgres-XC". The branch, master has been updated via baa0d2e4589347558b6fd894d431c1ff42151492 (commit) from b9c601ba5509e9c90f1d4d184a514ce47ed7397d (commit) - Log ----------------------------------------------------------------- commit baa0d2e4589347558b6fd894d431c1ff42151492 Author: Michael P <mic...@us...> Date: Thu Mar 31 19:31:02 2011 +0900 Fix for make -j This wasn't compiling correctly. Patch written from Wang Diancheng diff --git a/src/Makefile b/src/Makefile index 2ca5e05..918ad95 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,11 +18,11 @@ all install installdirs uninstall distprep: $(MAKE) -C timezone $@ # GTM should be built before backend because of dependancy $(MAKE) -C gtm $@ + $(MAKE) -C interfaces $@ $(MAKE) -C backend $@ $(MAKE) -C backend/utils/mb/conversion_procs $@ $(MAKE) -C backend/snowball $@ $(MAKE) -C include $@ - $(MAKE) -C interfaces $@ $(MAKE) -C backend/replication/libpqwalreceiver $@ $(MAKE) -C bin $@ $(MAKE) -C pl $@ ----------------------------------------------------------------------- Summary of changes: src/Makefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-31 09:08:43
|
Project "Postgres-XC". The branch, ha_support has been updated via 263fffdb2d9865eac2d6780b2ac7edb6d4c0b857 (commit) from 3df6c0f60081d0097939b34978d3d545f57b7d01 (commit) - Log ----------------------------------------------------------------- commit 263fffdb2d9865eac2d6780b2ac7edb6d4c0b857 Author: Koichi Suzuki <koi...@gm...> Date: Thu Mar 31 18:08:18 2011 +0900 This commit added headers to some of GTM source files. diff --git a/src/gtm/common/aset.c b/src/gtm/common/aset.c index 3c14fb1..300aa05 100644 --- a/src/gtm/common/aset.c +++ b/src/gtm/common/aset.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.77 2008/04/11 22:54:23 tgl Exp $ + * $Postgres-XC$ * * NOTE: * This is a new (Feb. 05, 1999) implementation of the allocation set diff --git a/src/gtm/common/assert.c b/src/gtm/common/assert.c index ea182d5..55da27b 100644 --- a/src/gtm/common/assert.c +++ b/src/gtm/common/assert.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/error/assert.c,v 1.35 2008/01/01 19:45:53 momjian Exp $ + * $Postgres-XC$ * * NOTE * This should eventually work with elog() diff --git a/src/gtm/gtm_ctl/gtm_ctl.c b/src/gtm/gtm_ctl/gtm_ctl.c index e6b277e..91690c9 100644 --- a/src/gtm/gtm_ctl/gtm_ctl.c +++ b/src/gtm/gtm_ctl/gtm_ctl.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/libpq/ip.c b/src/gtm/libpq/ip.c index 08929e9..3f719fc 100644 --- a/src/gtm/libpq/ip.c +++ b/src/gtm/libpq/ip.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/libpq/ip.c,v 1.43 2009/01/01 17:23:42 momjian Exp $ + * $Postgres-XC$ * * This file and the IPV6 implementation were initially provided by * Nigel Kukard <nk...@lb...>, Linux Based Systems Design diff --git a/src/gtm/libpq/pqcomm.c b/src/gtm/libpq/pqcomm.c index 4543665..4bc9aab 100644 --- a/src/gtm/libpq/pqcomm.c +++ b/src/gtm/libpq/pqcomm.c @@ -31,7 +31,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.198 2008/01/01 19:45:49 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/libpq/pqformat.c b/src/gtm/libpq/pqformat.c index 6d8e5f9..2bd6d59 100644 --- a/src/gtm/libpq/pqformat.c +++ b/src/gtm/libpq/pqformat.c @@ -25,7 +25,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/backend/libpq/pqformat.c,v 1.48 2009/01/01 17:23:42 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/libpq/pqsignal.c b/src/gtm/libpq/pqsignal.c index 0c7914e..39687bb 100644 --- a/src/gtm/libpq/pqsignal.c +++ b/src/gtm/libpq/pqsignal.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.44 2008/01/01 19:45:49 momjian Exp $ + * $Postgres-XC$ * * NOTES * This shouldn't be in libpq, but the monitor and some other diff --git a/src/gtm/libpq/strlcpy.c b/src/gtm/libpq/strlcpy.c index 28a3740..64fbac4 100644 --- a/src/gtm/libpq/strlcpy.c +++ b/src/gtm/libpq/strlcpy.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/port/strlcpy.c,v 1.5 2008/01/01 19:46:00 momjian Exp $ + * $Postgres-XC$ * * This file was taken from OpenBSD and is used on platforms that don't * provide strlcpy(). The OpenBSD copyright terms follow. diff --git a/src/gtm/main/gtm_seq.c b/src/gtm/main/gtm_seq.c index 60a612f..8195b39 100644 --- a/src/gtm/main/gtm_seq.c +++ b/src/gtm/main/gtm_seq.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_snap.c b/src/gtm/main/gtm_snap.c index c2d818b..6bf86a7 100644 --- a/src/gtm/main/gtm_snap.c +++ b/src/gtm/main/gtm_snap.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_stat.c b/src/gtm/main/gtm_stat.c index d9fa7aa..892e2f8 100644 --- a/src/gtm/main/gtm_stat.c +++ b/src/gtm/main/gtm_stat.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_stats.c b/src/gtm/main/gtm_stats.c index 2548cd4..297b8f8 100644 --- a/src/gtm/main/gtm_stats.c +++ b/src/gtm/main/gtm_stats.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_thread.c b/src/gtm/main/gtm_thread.c index 2fd6dc2..fe48e7c 100644 --- a/src/gtm/main/gtm_thread.c +++ b/src/gtm/main/gtm_thread.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_time.c b/src/gtm/main/gtm_time.c index 1e1451e..be30a46 100644 --- a/src/gtm/main/gtm_time.c +++ b/src/gtm/main/gtm_time.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/gtm_txn.c b/src/gtm/main/gtm_txn.c index 5715b40..9cfbeb6 100644 --- a/src/gtm/main/gtm_txn.c +++ b/src/gtm/main/gtm_txn.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/main/main.c b/src/gtm/main/main.c index 3fbf283..66096f5 100644 --- a/src/gtm/main/main.c +++ b/src/gtm/main/main.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/path/path.c b/src/gtm/path/path.c index 11c6290..7076afe 100644 --- a/src/gtm/path/path.c +++ b/src/gtm/path/path.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/gtm/recovery/register.c b/src/gtm/recovery/register.c index 0c40596..5f44425 100644 --- a/src/gtm/recovery/register.c +++ b/src/gtm/recovery/register.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/assert.h b/src/include/gtm/assert.h index 97cfc2d..ace5f7f 100644 --- a/src/include/gtm/assert.h +++ b/src/include/gtm/assert.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/elog.h b/src/include/gtm/elog.h index 9c410db..e21cac0 100644 --- a/src/include/gtm/elog.h +++ b/src/include/gtm/elog.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.98 2009/01/01 17:24:02 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm.h b/src/include/gtm/gtm.h index ad5882b..c2894e3 100644 --- a/src/include/gtm/gtm.h +++ b/src/include/gtm/gtm.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_c.h b/src/include/gtm/gtm_c.h index 116aa67..3d7c179 100644 --- a/src/include/gtm/gtm_c.h +++ b/src/include/gtm/gtm_c.h @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * c.h + * gtm_c.h * Fundamental C definitions. This is included by every .c file in * PostgreSQL (via either postgres.h or postgres_fe.h, as appropriate). * @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/c.h,v 1.234 2009/01/01 17:23:55 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_client.h b/src/include/gtm/gtm_client.h index c86a874..791468a 100644 --- a/src/include/gtm/gtm_client.h +++ b/src/include/gtm/gtm_client.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_conn.h b/src/include/gtm/gtm_conn.h index 40256be..f6c39d0 100644 --- a/src/include/gtm/gtm_conn.h +++ b/src/include/gtm/gtm_conn.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_ext.h b/src/include/gtm/gtm_ext.h index 49b0253..f8963ce 100644 --- a/src/include/gtm/gtm_ext.h +++ b/src/include/gtm/gtm_ext.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_ip.h b/src/include/gtm/gtm_ip.h index 2f89418..262af32 100644 --- a/src/include/gtm/gtm_ip.h +++ b/src/include/gtm/gtm_ip.h @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * ip.h + * gtm_ip.h * Definitions for IPv6-aware network access. * * These definitions are used by both frontend and backend code. Be careful @@ -9,7 +9,7 @@ * Copyright (c) 2003-2009, PostgreSQL Global Development Group * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/ip.h,v 1.20 2008/01/01 19:45:58 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_list.h b/src/include/gtm/gtm_list.h index 9ead69b..f73c9a1 100644 --- a/src/include/gtm/gtm_list.h +++ b/src/include/gtm/gtm_list.h @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * pg_list.h + * gtm_list.h * interface for PostgreSQL generic linked list package * * This package implements singly-linked homogeneous lists. @@ -31,7 +31,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/nodes/pg_list.h,v 1.59 2008/08/14 18:48:00 tgl Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_lock.h b/src/include/gtm/gtm_lock.h index 3da85c1..3404b3d 100644 --- a/src/include/gtm/gtm_lock.h +++ b/src/include/gtm/gtm_lock.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_msg.h b/src/include/gtm/gtm_msg.h index 4ec7dac..b3071a8 100644 --- a/src/include/gtm/gtm_msg.h +++ b/src/include/gtm/gtm_msg.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_proxy.h b/src/include/gtm/gtm_proxy.h index ee12fd5..4fcf5f0 100644 --- a/src/include/gtm/gtm_proxy.h +++ b/src/include/gtm/gtm_proxy.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_seq.h b/src/include/gtm/gtm_seq.h index 7e75445..c9e993c 100644 --- a/src/include/gtm/gtm_seq.h +++ b/src/include/gtm/gtm_seq.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_time.h b/src/include/gtm/gtm_time.h index 90f36ea..22d068d 100644 --- a/src/include/gtm/gtm_time.h +++ b/src/include/gtm/gtm_time.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/gtm_txn.h b/src/include/gtm/gtm_txn.h index 86a0d49..5b5f75b 100644 --- a/src/include/gtm/gtm_txn.h +++ b/src/include/gtm/gtm_txn.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/ip.h b/src/include/gtm/ip.h index fa4e3d3..cdd69ba 100644 --- a/src/include/gtm/ip.h +++ b/src/include/gtm/ip.h @@ -9,7 +9,7 @@ * Copyright (c) 2003-2009, PostgreSQL Global Development Group * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/ip.h,v 1.20 2008/01/01 19:45:58 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/libpq-be.h b/src/include/gtm/libpq-be.h index c73335d..8e9805f 100644 --- a/src/include/gtm/libpq-be.h +++ b/src/include/gtm/libpq-be.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.69 2009/01/01 17:23:59 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/libpq-fe.h b/src/include/gtm/libpq-fe.h index 1ae16c1..44ebf58 100644 --- a/src/include/gtm/libpq-fe.h +++ b/src/include/gtm/libpq-fe.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.145 2009/01/01 17:24:03 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/libpq-int.h b/src/include/gtm/libpq-int.h index 5c6714b..30775e3 100644 --- a/src/include/gtm/libpq-int.h +++ b/src/include/gtm/libpq-int.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.139 2009/01/01 17:24:03 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/memnodes.h b/src/include/gtm/memnodes.h index 9c55e46..8f5d3e4 100644 --- a/src/include/gtm/memnodes.h +++ b/src/include/gtm/memnodes.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/nodes/memnodes.h,v 1.34 2008/01/01 19:45:58 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/memutils.h b/src/include/gtm/memutils.h index 9666c44..fc1e2d3 100644 --- a/src/include/gtm/memutils.h +++ b/src/include/gtm/memutils.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/utils/memutils.h,v 1.64 2008/01/01 19:45:59 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/palloc.h b/src/include/gtm/palloc.h index e81e9d1..2efaaa4 100644 --- a/src/include/gtm/palloc.h +++ b/src/include/gtm/palloc.h @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/utils/palloc.h,v 1.40 2008/06/28 16:45:22 tgl Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/path.h b/src/include/gtm/path.h index e95ca5e..6f18856 100644 --- a/src/include/gtm/path.h +++ b/src/include/gtm/path.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/pqcomm.h b/src/include/gtm/pqcomm.h index e0de16e..1544615 100644 --- a/src/include/gtm/pqcomm.h +++ b/src/include/gtm/pqcomm.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/pqcomm.h,v 1.109 2008/10/28 12:10:44 mha Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/pqexpbuffer.h b/src/include/gtm/pqexpbuffer.h index 039a481..6e4f586 100644 --- a/src/include/gtm/pqexpbuffer.h +++ b/src/include/gtm/pqexpbuffer.h @@ -19,7 +19,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/interfaces/libpq/pqexpbuffer.h,v 1.21 2008/11/26 16:23:11 tgl Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/pqformat.h b/src/include/gtm/pqformat.h index 4a07367..e5b4541 100644 --- a/src/include/gtm/pqformat.h +++ b/src/include/gtm/pqformat.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/pqformat.h,v 1.27 2009/01/01 17:23:59 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/pqsignal.h b/src/include/gtm/pqsignal.h index 523a151..ce90997 100644 --- a/src/include/gtm/pqsignal.h +++ b/src/include/gtm/pqsignal.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/libpq/pqsignal.h,v 1.32 2008/01/01 19:45:58 momjian Exp $ + * $Postgres-XC$ * * NOTES * This shouldn't be in libpq, but the monitor and some other diff --git a/src/include/gtm/register.h b/src/include/gtm/register.h index 7c2461f..0a43bf1 100644 --- a/src/include/gtm/register.h +++ b/src/include/gtm/register.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL$ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ diff --git a/src/include/gtm/stringinfo.h b/src/include/gtm/stringinfo.h index c34e6a3..d504685 100644 --- a/src/include/gtm/stringinfo.h +++ b/src/include/gtm/stringinfo.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2011 Nippon Telegraph and Telephone Corporation * - * $PostgreSQL: pgsql/src/include/lib/stringinfo.h,v 1.35 2008/01/01 19:45:57 momjian Exp $ + * $Postgres-XC$ * *------------------------------------------------------------------------- */ ----------------------------------------------------------------------- Summary of changes: src/gtm/common/aset.c | 2 +- src/gtm/common/assert.c | 2 +- src/gtm/gtm_ctl/gtm_ctl.c | 2 +- src/gtm/libpq/ip.c | 2 +- src/gtm/libpq/pqcomm.c | 2 +- src/gtm/libpq/pqformat.c | 2 +- src/gtm/libpq/pqsignal.c | 2 +- src/gtm/libpq/strlcpy.c | 2 +- src/gtm/main/gtm_seq.c | 2 +- src/gtm/main/gtm_snap.c | 2 +- src/gtm/main/gtm_stat.c | 2 +- src/gtm/main/gtm_stats.c | 2 +- src/gtm/main/gtm_thread.c | 2 +- src/gtm/main/gtm_time.c | 2 +- src/gtm/main/gtm_txn.c | 2 +- src/gtm/main/main.c | 2 +- src/gtm/path/path.c | 2 +- src/gtm/recovery/register.c | 2 +- src/include/gtm/assert.h | 2 +- src/include/gtm/elog.h | 2 +- src/include/gtm/gtm.h | 2 +- src/include/gtm/gtm_c.h | 4 ++-- src/include/gtm/gtm_client.h | 2 +- src/include/gtm/gtm_conn.h | 2 +- src/include/gtm/gtm_ext.h | 2 +- src/include/gtm/gtm_ip.h | 4 ++-- src/include/gtm/gtm_list.h | 4 ++-- src/include/gtm/gtm_lock.h | 2 +- src/include/gtm/gtm_msg.h | 2 +- src/include/gtm/gtm_proxy.h | 2 +- src/include/gtm/gtm_seq.h | 2 +- src/include/gtm/gtm_time.h | 2 +- src/include/gtm/gtm_txn.h | 2 +- src/include/gtm/ip.h | 2 +- src/include/gtm/libpq-be.h | 2 +- src/include/gtm/libpq-fe.h | 2 +- src/include/gtm/libpq-int.h | 2 +- src/include/gtm/memnodes.h | 2 +- src/include/gtm/memutils.h | 2 +- src/include/gtm/palloc.h | 2 +- src/include/gtm/path.h | 2 +- src/include/gtm/pqcomm.h | 2 +- src/include/gtm/pqexpbuffer.h | 2 +- src/include/gtm/pqformat.h | 2 +- src/include/gtm/pqsignal.h | 2 +- src/include/gtm/register.h | 2 +- src/include/gtm/stringinfo.h | 2 +- 47 files changed, 50 insertions(+), 50 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 16:15:12
|
Project "Postgres-XC". The branch, master has been updated via b9c601ba5509e9c90f1d4d184a514ce47ed7397d (commit) from 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) - Log ----------------------------------------------------------------- commit b9c601ba5509e9c90f1d4d184a514ce47ed7397d Author: Michael P <mic...@us...> Date: Thu Mar 31 01:12:15 2011 +0900 Fix for bug 3160456: sequence error values If an error occured on GTM for currval or nextval, the incorrect value EINVAL (22) was returned to Postgres-XC node. diff --git a/src/gtm/main/gtm_seq.c b/src/gtm/main/gtm_seq.c index f6c4a21..6a863d2 100644 --- a/src/gtm/main/gtm_seq.c +++ b/src/gtm/main/gtm_seq.c @@ -657,7 +657,7 @@ GTM_SeqGetCurrent(GTM_SequenceKey seqkey) ereport(LOG, (EINVAL, errmsg("The sequence with the given key does not exist"))); - return EINVAL; + return InvalidSequenceValue; } GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); @@ -719,7 +719,7 @@ GTM_SeqGetNext(GTM_SequenceKey seqkey) ereport(LOG, (EINVAL, errmsg("The sequence with the given key does not exist"))); - return EINVAL; + return InvalidSequenceValue; } GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); ----------------------------------------------------------------------- Summary of changes: src/gtm/main/gtm_seq.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 15:32:00
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been deleted was 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 ----------------------------------------------------------------------- 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 Fix GXID feed issue ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 15:30:16
|
Project "Postgres-XC". The branch, REL0_9_4_STABLE has been created at 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 15:28:53
|
Project "Postgres-XC". The annotated tag, v0.9.4 has been created at 3ac5a29e291e47af2ba420685c6776012a26779c (tag) tagging 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) replaces v0.9.3 tagged by Michael P on Thu Mar 31 00:27:51 2011 +0900 - Log ----------------------------------------------------------------- Postgres-XC version 0.9.4 tag Abbas (16): Block creation of concurrent indices To avoid a crash caused by an insert select statement in vacuum.sql To fix a server crash in aggregates as reported in ID 3125430 GetRelationLocInfo can return NULL, this patch adds check for a NULL return at missing places Block FK Constraints and add some missing checks The test case portals finds a NULL connecction in ExecEndRemoteQuery and crashes the server. This patch puts a NULL check to avoid the crash Fixing a few expected output files and changed a warning message to make the output independent of the cluster configuration Add alternate expected output files to take care of regression failures Expected output changed to fix regression failure Add alternate expected output file to fix regression falilure of numeric.sql Fix for server crash 3148037 : does not fix WHERE CURRENT OF, only fixes server crash Fix for server crash as mentioned in bug ID 3170715 Since the creation of unique indices is supposed to fail in XC hence this output is correct This patch fixes a test case in strings.sql This patch fixes the problem in XC that error detail was not being handled. Merge branch 'merge_postgres_9_0_3' of ssh://postgres-xc.git.sourceforge.net/gitroot/postgres-xc/postgres-xc into merge_postgres_9_0_3 Mason Sharp (22): Special hanlding for ANALYZE on the data nodes. Improve performance of "multi-step" queries (an on-going process). Fix bug with primary key in CREATE TABLE statement. Add a message that the RETURNING clause is not yet supported. 1. Support for UPDATE and DELETE WHERE CURRENT OF for Support for COPY SELECT Do not allow the partition column to be updated on hash partitioned Fix some compiler warnings Fix PGXC macro usage Minor cursor changes: Fix for sourceforge.net bug#3013984: Sequence scope Fixed bug where if there are subqueries in the SELECT clause This fixes a couple of issues noticed after the last commit, Add support for INSERT SELECT. Fix a problem when more values are selected than total columns in Fixed a bug with INSERT SELECT when an input value is NULL. Fixed bug in INSERT when omitting a value for the partitioning column. Fixed recently introduced bug with node determination Add support for single-step prepared statements. Added missing #ifdef PGXC Updated regression tests. Block the creation of temp tables until properly supported Michael P (110): Support for CLEAN CONNECTION Block Node Commit on a Datanode. Change Protocol connection between PGXC nodes and GTM/GTM-Proxy. Correction for implicit 2PC Clean up of execRemote.c Improvement of performance with tuple scan Fix for bug 3142311:renaming sequences error Fix for bug 3136262: Improvement of Explicit 2PC error handling Sequence Renaming Node Registering feature Allow only Remote Coordinator to use functionnalities introduced with SQL/MED Fix for partially committed transactions in Implicit 2PC Clean up in Materialize code Fix and Clean up in Executor Base code to support correlated DELETE and UPDATE Support for correlated DELETE for replicated tables The patch implements multiple insert syntax in PGXC. Fix for make -j Fix for bug 3147497 INSERT.. DEFAULT VALUES Fix for replicated tables using multi-INSERT queries. maintenance for 2011, change header files Support for EXECUTE DIRECT CREATE TABLE: new distribution function MODULO Fix for bug 3142430 Fix for bug 3172438: node registration protocol Multiple INSERT support for MODULO tables Fix for bug 3170713: DROP DATABASE wihout cleaning connections Fix for bug 3170708: Default values support for MULTI INSERT Fix for bug 3188711: Fire rules only on Coordinator Block SAVEPOINT because of non-support Fix for bug 3136262: PREPARE information not correctly got Fix for DROP DATABASE Fix for bug 3151626: Support for COPY BINARY Fix for bug 3134395, 3086422, 3136230: 2PC locks Merge with PostgreSQL 9.0.3 Fix for bug 3199029 GTM/GTM-proxy FATAL error handling Merge branch 'master' into merge_postgres_9_0_3 Improve error handling when launching DDL or utilities Merge branch 'master' into merge_postgres_9_0_3 Fix for CREATE INDEX CONCURRENTLY Block PREPARE and EXECUTE for the time being CREATE TABLE default distribution to REPLICATED Change back table defalt type to distributed. Addition of correct output for regress test float4. Fix regression tests for int4 Fix for regression tests float4 Partial fix for regression test float fix Fix for regression test create_table Fix for regression test txid Block trigger as this feature is not supported Partial fix for regression test temp Block FOREIGN constraint creation Block TEMP SEQUENCE and TABLESPACE Fix when transforming a CREATE statement Cleanup of regression files Fix for regression test create_table Fix for regression test returning Fix for regression test inet Block SERIAL sequences Fix for bug 3201711: Sequence view crash Fix for regression test box Fix for bug 3202643: Sequence error Stabilize code for pg_regress tests Fix for bugs 3148479, 3140473: COPY FROM CVS HEADER, COPY TO WITH CSV QUOTE Fix for bug 3141640: non column select Fix for bugs 3124253 and 3202554: Unique remote query node Fix for bug 3205043: pg_dump support for MODULO table Clean up of pgxc_ddl Merge branch 'master' into merge_postgres_9_0_3 Fix for regression test tablespace Fix for regression test point Fix for regression test box Fix for regression test triggers Fix for regression test prepare Fix for regression test case Fix for regression test guc Fix for regression test update Fix for regression test delete Fix for regression test plancache Fix for regression test combocid Fix for regression test copy and point Fix for regression test copyselect Fix for regression test create_misc Fix for regression test create_aggregate Fix for regression test typed_table Fix for regression test sanity_check Fix for regression test select Fix for regression test select_distinct_on Fix for regression test union Fix for regression test transactions Fix for regression test random Fix for regression test hash_index Fix for regression test namespace Fix for regression test portals_p2 Fix for regression test cluster Fix for regression test dependency Fix for regression test rowtypes Fix for regression test returning Fix for regression test select_into Fix for regression test copy2 Fix for regression test truncate Block DEFERRED constraints (DEFERRABLE) Fix for cache lookup bug for type Addition of a check when fetching tuples Fix for regression test create type Fix for regression test privileges Fix for VIEW and SEQUENCE Fix a cache leak WARNING with system cache Fix for bug 3240318: support for lastval Fix GXID feed issue Pavan Deolasee (1): Check for buffer overflow while constructing gtm/gtm_proxy start/stop commands. ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-30 15:13:26
|
Project "Postgres-XC". The branch, POSTGRES8_4_3_BASE has been created at 490c08dd37fa44af57cd3a2b3e931ef4f3a94853 (commit) - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@gm...> - 2011-03-30 12:01:56
|
Thank you Michael; I remember we had similar issue in the past... ---------- Koichi Suzuki 2011/3/30 Michael Paquier <mic...@us...>: > Project "Postgres-XC". > > The branch, merge_postgres_9_0_3 has been updated > via 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) > from 886f9bbe99120dc751a7d9110521a7cd6cc884d9 (commit) > > > - Log ----------------------------------------------------------------- > commit 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 > Author: Michael P <mic...@us...> > Date: Wed Mar 30 20:25:52 2011 +0900 > > Fix GXID feed issue > > Useless calls to GetCurrentTransactionId were the origin > of consuming extra transaction IDs even on backend Datanode > where it should ot take a transaction ID at some moments. > > This problem may cause node crash, due to same transaction IDs being committed > twice or pooler connection issues. > > diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c > index 0b09093..ed6271e 100644 > --- a/src/backend/access/transam/xact.c > +++ b/src/backend/access/transam/xact.c > @@ -1923,13 +1923,16 @@ CommitTransaction(bool contact_gtm) > bool PrepareLocalCoord = false; > bool PreparePGXCNodes = false; > char implicitgid[256]; > - TransactionId xid = GetCurrentTransactionId(); > + TransactionId xid = InvalidTransactionId; > > if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && contact_gtm) > PreparePGXCNodes = PGXCNodeIsImplicit2PC(&PrepareLocalCoord); > > if (PrepareLocalCoord || PreparePGXCNodes) > + { > + xid = GetCurrentTransactionId(); > sprintf(implicitgid, "T%d", xid); > + } > > /* Save GID where PrepareTransaction can find it again */ > if (PrepareLocalCoord) > > ----------------------------------------------------------------------- > > Summary of changes: > src/backend/access/transam/xact.c | 5 ++++- > 1 files changed, 4 insertions(+), 1 deletions(-) > > > hooks/post-receive > -- > Postgres-XC > > ------------------------------------------------------------------------------ > Enable your software for Intel(R) Active Management Technology to meet the > growing manageability and security demands of your customers. Businesses > are taking advantage of Intel(R) vPro (TM) technology - will your software > be a part of the solution? Download the Intel(R) Manageability Checker > today! http://p.sf.net/sfu/intel-dev2devmar > _______________________________________________ > Postgres-xc-committers mailing list > Pos...@li... > https://lists.sourceforge.net/lists/listinfo/postgres-xc-committers > |
From: Michael P. <mic...@us...> - 2011-03-30 11:28:56
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 (commit) from 886f9bbe99120dc751a7d9110521a7cd6cc884d9 (commit) - Log ----------------------------------------------------------------- commit 46f524e5a6430735c6549afbbe0ea61ab8a4cd49 Author: Michael P <mic...@us...> Date: Wed Mar 30 20:25:52 2011 +0900 Fix GXID feed issue Useless calls to GetCurrentTransactionId were the origin of consuming extra transaction IDs even on backend Datanode where it should ot take a transaction ID at some moments. This problem may cause node crash, due to same transaction IDs being committed twice or pooler connection issues. diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 0b09093..ed6271e 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -1923,13 +1923,16 @@ CommitTransaction(bool contact_gtm) bool PrepareLocalCoord = false; bool PreparePGXCNodes = false; char implicitgid[256]; - TransactionId xid = GetCurrentTransactionId(); + TransactionId xid = InvalidTransactionId; if (IS_PGXC_COORDINATOR && !IsConnFromCoord() && contact_gtm) PreparePGXCNodes = PGXCNodeIsImplicit2PC(&PrepareLocalCoord); if (PrepareLocalCoord || PreparePGXCNodes) + { + xid = GetCurrentTransactionId(); sprintf(implicitgid, "T%d", xid); + } /* Save GID where PrepareTransaction can find it again */ if (PrepareLocalCoord) ----------------------------------------------------------------------- Summary of changes: src/backend/access/transam/xact.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-30 08:40:30
|
Project "Postgres-XC". The branch, ha_support has been updated via 82670fcb1bf768267195f9a9c33d6f9207ba917b (commit) via 073ac85b8c94800eacd9f2d7f8555a8ae9453022 (commit) from 418e9c622429131005817538966cd50d4779e6dd (commit) - Log ----------------------------------------------------------------- commit 82670fcb1bf768267195f9a9c33d6f9207ba917b Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 17:20:45 2011 +0900 Revert "Revert "This is to change the file name of gtm.c at src/pgxc/pgxc_clean to"" This reverts commit 073ac85b8c94800eacd9f2d7f8555a8ae9453022. This is to cancel name change of pgxc_clean to fix build problem. diff --git a/src/pgxc/pgxc_clean/Makefile b/src/pgxc/pgxc_clean/Makefile index 10cba88..5d41e1a 100644 --- a/src/pgxc/pgxc_clean/Makefile +++ b/src/pgxc/pgxc_clean/Makefile @@ -18,7 +18,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) xcm_builddir = $(top_builddir)/src/pgxc/xcm gtm_builddir = $(top_builddir)/src/gtm -OBJS= pgxc_clean.o common.o subfunc.o txnctl.o gtm.o +OBJS= pgxc_clean.o common.o subfunc.o txnctl.o pgxc_clean_gtm.o # Switch when libxcm and libgtmclient are installed via 'make install' # EX_OBJS = $(gtm_builddir)/common/assert.o EX_OBJS = $(gtm_builddir)/common/assert.o \ diff --git a/src/pgxc/pgxc_clean/gtm.c b/src/pgxc/pgxc_clean/pgxc_clean_gtm.c similarity index 100% rename from src/pgxc/pgxc_clean/gtm.c rename to src/pgxc/pgxc_clean/pgxc_clean_gtm.c commit 073ac85b8c94800eacd9f2d7f8555a8ae9453022 Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 17:18:28 2011 +0900 Revert "This is to change the file name of gtm.c at src/pgxc/pgxc_clean to" This reverts commit 418e9c622429131005817538966cd50d4779e6dd. Cmmit reverted to restore to the status before pgxc_clean is added. Found erro r to fix. Sorry. diff --git a/src/pgxc/pgxc_clean/Makefile b/src/pgxc/pgxc_clean/Makefile index 5d41e1a..10cba88 100644 --- a/src/pgxc/pgxc_clean/Makefile +++ b/src/pgxc/pgxc_clean/Makefile @@ -18,7 +18,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) xcm_builddir = $(top_builddir)/src/pgxc/xcm gtm_builddir = $(top_builddir)/src/gtm -OBJS= pgxc_clean.o common.o subfunc.o txnctl.o pgxc_clean_gtm.o +OBJS= pgxc_clean.o common.o subfunc.o txnctl.o gtm.o # Switch when libxcm and libgtmclient are installed via 'make install' # EX_OBJS = $(gtm_builddir)/common/assert.o EX_OBJS = $(gtm_builddir)/common/assert.o \ diff --git a/src/pgxc/pgxc_clean/pgxc_clean_gtm.c b/src/pgxc/pgxc_clean/gtm.c similarity index 100% rename from src/pgxc/pgxc_clean/pgxc_clean_gtm.c rename to src/pgxc/pgxc_clean/gtm.c ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-30 08:04:49
|
Project "Postgres-XC". The branch, ha_support has been updated via 418e9c622429131005817538966cd50d4779e6dd (commit) from dcc82f72fb630f16c965e1e6d3d93b2c6008a150 (commit) - Log ----------------------------------------------------------------- commit 418e9c622429131005817538966cd50d4779e6dd Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 17:03:58 2011 +0900 This is to change the file name of gtm.c at src/pgxc/pgxc_clean to pgxc_clean_gtm.c to avoid confusion. diff --git a/src/pgxc/pgxc_clean/Makefile b/src/pgxc/pgxc_clean/Makefile index 10cba88..5d41e1a 100644 --- a/src/pgxc/pgxc_clean/Makefile +++ b/src/pgxc/pgxc_clean/Makefile @@ -18,7 +18,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) xcm_builddir = $(top_builddir)/src/pgxc/xcm gtm_builddir = $(top_builddir)/src/gtm -OBJS= pgxc_clean.o common.o subfunc.o txnctl.o gtm.o +OBJS= pgxc_clean.o common.o subfunc.o txnctl.o pgxc_clean_gtm.o # Switch when libxcm and libgtmclient are installed via 'make install' # EX_OBJS = $(gtm_builddir)/common/assert.o EX_OBJS = $(gtm_builddir)/common/assert.o \ diff --git a/src/pgxc/pgxc_clean/gtm.c b/src/pgxc/pgxc_clean/pgxc_clean_gtm.c similarity index 100% rename from src/pgxc/pgxc_clean/gtm.c rename to src/pgxc/pgxc_clean/pgxc_clean_gtm.c ----------------------------------------------------------------------- Summary of changes: src/pgxc/pgxc_clean/Makefile | 2 +- src/pgxc/pgxc_clean/{gtm.c => pgxc_clean_gtm.c} | 0 2 files changed, 1 insertions(+), 1 deletions(-) rename src/pgxc/pgxc_clean/{gtm.c => pgxc_clean_gtm.c} (100%) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-30 03:42:05
|
Project "Postgres-XC". The branch, ha_support has been updated via dcc82f72fb630f16c965e1e6d3d93b2c6008a150 (commit) from 5dbdc5f9e7460a0f1f06cbbba96303a8bf7465fb (commit) - Log ----------------------------------------------------------------- commit dcc82f72fb630f16c965e1e6d3d93b2c6008a150 Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 12:41:37 2011 +0900 This is an additional commit for pgxc_clean to modifie it's parent Makefile to include pgxc_clean make. diff --git a/src/pgxc/Makefile b/src/pgxc/Makefile index 5ba9ac1..2156013 100644 --- a/src/pgxc/Makefile +++ b/src/pgxc/Makefile @@ -13,7 +13,7 @@ subdir = src/pgxc top_builddir = ../.. include $(top_builddir)/src/Makefile.global -DIRS = xcm +DIRS = xcm pgxc_clean all install installdirs uninstall distprep clean distclean maintainer-clean: $(INSTALL_DATA) $(srcdir)/xcm/pgxc_ha.conf.sample '$(DESTDIR)$(datadir)/pgxc_ha.conf.sample' ----------------------------------------------------------------------- Summary of changes: src/pgxc/Makefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-03-30 03:08:40
|
Project "Postgres-XC". The branch, ha_support has been updated via 5dbdc5f9e7460a0f1f06cbbba96303a8bf7465fb (commit) from 4d3f0a48a979044c6b741f9cd7d4dc37c32548e2 (commit) - Log ----------------------------------------------------------------- commit 5dbdc5f9e7460a0f1f06cbbba96303a8bf7465fb Author: Koichi Suzuki <koi...@gm...> Date: Wed Mar 30 12:02:46 2011 +0900 This commit is to add "pgxc_clean" tools for HA-support. When a coordinator fails, transactions handled in the coordinator may fail. HOwever, the other coordinator can continue to handle incoming transactions. On the other hand, if there's prepared but not committed/aborted transactions originated from the failed coordinator, it will reman as "unfinished transactions" whose GXID will continue to appear in global snapshots, which gives bad influence to the performance. pgxc_clean deals with this situation. It looks for 2PC transactions and if it is originated by the failed coordinator and if they are not finished. Then pgxc_config will commit or abort (depending upon the whole status of local commits) such transactions so that they don't appear in snapshots. This is implemented by Metro Systems. diff --git a/src/pgxc/pgxc_clean/Makefile b/src/pgxc/pgxc_clean/Makefile new file mode 100644 index 0000000..10cba88 --- /dev/null +++ b/src/pgxc/pgxc_clean/Makefile @@ -0,0 +1,51 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/pgxc/pgxc_clean +# +# Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation +# +# $PostgreSQL$ +# +#------------------------------------------------------------------------- + +PGFILEDESC = "pgxc_clean - Abort prepared transaction for a Postgres-XC Coordinator" +subdir = src/pgxc/pgxc_clean +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) + +xcm_builddir = $(top_builddir)/src/pgxc/xcm +gtm_builddir = $(top_builddir)/src/gtm + +OBJS= pgxc_clean.o common.o subfunc.o txnctl.o gtm.o +# Switch when libxcm and libgtmclient are installed via 'make install' +# EX_OBJS = $(gtm_builddir)/common/assert.o +EX_OBJS = $(gtm_builddir)/common/assert.o \ + $(gtm_builddir)/client/libgtmclient.a \ + $(xcm_builddir)/libxcm.a + +override LDFLAGS += -L$(top_builddir)/src/gtm/client \ + -L$(top_builddir)/src/pgxc/xcm + +# Switch when libxcm and libgtmclient are installed via 'make install' +# LIBS= -lpthread -lxcm -lgtmclient +LIBS= -lpthread + +all: pgxc_clean + +pgxc_clean: $(OBJS) + $(CC) $(CFLAGS) $(OBJS) $(EX_OBJS) $(libpq_pgport) $(LDFLAGS) $(LIBS) -o $@$(X) + +install: all installdirs + $(INSTALL_PROGRAM) pgxc_clean$(X) '$(DESTDIR)$(bindir)'/pgxc_clean$(X) + +installdirs: + $(mkinstalldirs) '$(DESTDIR)$(bindir)' + +uninstall: + rm -f $(addprefix '$(DESTDIR)$(bindir)'/, pgxc_clean$(X)) + +clean distclean maintainer-clean: + rm -f pgxc_clean$(X) $(OBJS) pgxc_clean.o + diff --git a/src/pgxc/pgxc_clean/README b/src/pgxc/pgxc_clean/README new file mode 100644 index 0000000..a93d617 --- /dev/null +++ b/src/pgxc/pgxc_clean/README @@ -0,0 +1,55 @@ + +Notes on pgxc_clean +================ + +1. Abstract: +------------ + +pgxc_clean is a command line tool which recover 2PC-transactions which are +originated by crashed coordinator. + +2. Usage: +--------- + +Usage: + pgxc_clean --version + pgxc_clean --help + pgxc_clean [--all|--node=NODE_NUMBER] [--user=USERNAME] [--password=PASSWORD] + +General options: + --help show help, then exit + --version output version information, then exit + +Options for originator: + -a, --all all Coordinators in the cluster + -n, --node=NODE_NUMBER given Coordinator number + +Connection options: + -U, --user=USERNAME username to be used to establish connection + against coordinator + -W, --password=PASSWORD password to be used to establish connection + against coordinator + +3. Logging: +----------- + +pgxc_clean uses stdout to output non-error messages, and uses stderr to output +error or warning messages. + +4. Exit status: +--------------- + +pgxc_clean uses different exit codes for each type of error. + + 0: cleanup has been finished successfully + 4: wrong arguement was specified in command line + 6: pgxc_clean tried to connect to all running coordinators, but none of + them accepts connection request + 8: some kind of problem has occurred on GTM component + 9: some kind of problem has occurred on xcm component + 10: some kind of problem has occurred on coordinator component + 11: some kind of problem has occurred on datanode component + 12: pgxc_clean found transaction which has invalid status, such as + committed on a node but aborted on another node + 16: pgxc_clean encountered internal error, mostly out-of-memory + diff --git a/src/pgxc/pgxc_clean/common.c b/src/pgxc/pgxc_clean/common.c new file mode 100644 index 0000000..3f01f67 --- /dev/null +++ b/src/pgxc/pgxc_clean/common.c @@ -0,0 +1,81 @@ +/*------------------------------------------------------------------------- + * + * common.c + * common functions for pgxc_clean + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "pgxc_clean.h" + +extern const char *progname; + +/* + * output messages to console + * to stderr: warning and error message + * to stdout: others + */ +void +dispmsg(errlevel el, const char *format, ...) +{ + va_list vl; + time_t t; + struct tm *now; + const char *lvlstr[] = {"[?] ", "[I] ", "[W] ", "[E] ", "[D] "}; + + /* ignore debug messages in non-debug build */ +#ifndef DEBUG + if (el == lvl_debug) + return; +#endif + + time(&t); + now = localtime(&t); + + + if (el == lvl_warn || el == lvl_error) + fprintf(stderr, "[%s] %04d/%02d/%02d %02d:%02d:%02d ", + progname, now->tm_year+1900, now->tm_mon+1, now->tm_mday, + now->tm_hour, now->tm_min, now->tm_sec); + else + fprintf(stdout, "[%s] %04d/%02d/%02d %02d:%02d:%02d ", + progname, now->tm_year+1900, now->tm_mon+1, now->tm_mday, + now->tm_hour, now->tm_min, now->tm_sec); + + switch (el) + { + case lvl_info: + fprintf(stdout, lvlstr[el]); + break; + case lvl_warn: + case lvl_error: + fprintf(stderr, lvlstr[el]); + break; + case lvl_debug: + fprintf(stdout, lvlstr[el]); + break; + default: + fprintf(stdout, lvlstr[0]); + break; + } + + va_start(vl, format); + if (el == lvl_warn || el == lvl_error) + vfprintf(stderr, format, vl); + else + vfprintf(stdout, format, vl); + va_end(vl); + + if (el == lvl_warn || el == lvl_error) + fprintf(stderr, "\n"); + else + { + fprintf(stdout, "\n"); + fflush(stdout); + } +} diff --git a/src/pgxc/pgxc_clean/gtm.c b/src/pgxc/pgxc_clean/gtm.c new file mode 100644 index 0000000..e188ba2 --- /dev/null +++ b/src/pgxc/pgxc_clean/gtm.c @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------------- + * + * gtm.c + * GTM accessing functions + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/xact.h" +#include "gtm/gtm_client.h" +#include "gtm/libpq-int.h" +#include "pgxc/xcm/node_membership.h" + +#include "pgxc_clean.h" + +static GTM_Conn *conn_gtm; /* connection to the GTM */ + +/* + * connect2gtm + * connect to GTM, not GTM-proxy + */ +void +connect2gtm(void) +{ + int nRet; + xcm_connPoint *conn_pts; + int n_connections; + char connstr[256]; + + /* XXX should use gtm_proxy? */ + nRet = get_xcm_gtm_connPoints(1, &conn_pts, &n_connections); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, "couldn't get connection point for GTM"); + exit(RESULT_ERR_XCM); + } + + /* build connection string, we don't check overflow */ + snprintf(connstr, sizeof(connstr), + "host=%s port=%d pgxc_node_id=%d remote_type=%d", + conn_pts->addr, conn_pts->port, 0, PGXC_NODE_COORDINATOR); + dispmsg(lvl_debug, "connstr for GTM is \"%s\"", connstr); + free_xcm_connPoints(conn_pts, n_connections); + + /* connect to GTM */ + conn_gtm = connect_gtm(connstr); + if (GTMPQstatus(conn_gtm) != CONNECTION_OK) + { + dispmsg(lvl_error, "couldn't connect to GTM: %s", + GTMPQerrorMessage(conn_gtm)); + exit(RESULT_ERR_GTM); + } + + dispmsg(lvl_debug, "connected to GTM"); +} + +/* + * disconnect2gtm + * disconnect from GTM + */ +void +disconnect2gtm(void) +{ + disconnect_gtm(conn_gtm); +} + +/* + * remove_gxid_from_snapshot + * remove gid of transaction which has been cleaned-up from GTM's snapshot + */ +void +remove_gxid_from_snapshot(GlobalTransactionId gxid, bool iscommit) +{ + dispmsg(lvl_debug, "BEGIN: remove_gxid_from_snapshot(gid=%d, %s)", + gxid, iscommit ? "commit" : "rollback"); + + if (GTMPQstatus(conn_gtm) != CONNECTION_OK) + { + dispmsg(lvl_error, "invalid connection for GTM: %s", + GTMPQerrorMessage(conn_gtm)); + exit(RESULT_ERR_INTERNAL); + } + + /* do cleanup */ + if (commit_transaction(conn_gtm, gxid) != 0) + { + dispmsg(lvl_error, "couldn't remove GXID from snapshot: %s", + GTMPQerrorMessage(conn_gtm)); + exit(RESULT_ERR_GTM); + } + dispmsg(lvl_debug, "gxid=%u removed from snapshot", gxid); +} + +/* + * dump_snapshot + * dump current snapshot in the GTM node + */ +#ifdef DEBUG +void +dump_snapshot(void) +{ + GTM_SnapshotData *snapshot; + GlobalTransactionId gxid; + uint32 snidx; + + dispmsg(lvl_debug, "== %s() ======================", __FUNCTION__); + + gxid = begin_transaction(conn_gtm, GTM_ISOLATION_RC, NULL); + if (gxid == InvalidGlobalTransactionId) + { + dispmsg(lvl_error, "BEGIN transaction failed: %s", + GTMPQerrorMessage(conn_gtm)); + return; + } + else + dispmsg(lvl_debug, "Started a new transaction (GXID:%u)", gxid); + + snapshot = get_snapshot(conn_gtm, gxid, true); + if (snapshot == NULL) + dispmsg(lvl_error, "couldn't get snapshot: %s", + GTMPQerrorMessage(conn_gtm)); + else + for (snidx = 0; snidx < snapshot->sn_xcnt; snidx++) + dispmsg(lvl_debug, "sn_xip[%u]=%d", snidx, snapshot->sn_xip[snidx]); + + if (commit_transaction(conn_gtm, gxid)) + dispmsg(lvl_debug, "COMMIT failed (GXID:%u): %s", gxid, + GTMPQerrorMessage(conn_gtm)); + + dispmsg(lvl_debug, "== %s() ======================", __FUNCTION__); +} +#endif diff --git a/src/pgxc/pgxc_clean/pgxc_clean.c b/src/pgxc/pgxc_clean/pgxc_clean.c new file mode 100644 index 0000000..e81230d --- /dev/null +++ b/src/pgxc/pgxc_clean/pgxc_clean.c @@ -0,0 +1,337 @@ +/*------------------------------------------------------------------------- + * + * pgxc_clean.c + * pgxc_clean is a recovery tool for the coordinator crash. + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "getopt_long.h" + +#include "pgxc_clean.h" +#include "txnctl.h" + +extern char *optarg; +extern int optind, + opterr; + +/* Global */ +const char *progname; + +/* number of nodes */ +int all_coordinator_cnt; /* # of coordinators in the cluster */ +int all_datanode_cnt; /* # of datanodes in the cluster */ +int all_mirror_cnt; /* # of datanode mirrors in the cluster */ + +/* status of each node */ +unsigned *coordsts; /* status of each coordinator */ +MirrorStatus *mirrorsts; /* status of each datanode mirrors */ + +/* result summary */ +uint32 committed; /* number of committed txns */ +uint32 aborted; /* number of aborted txns */ +uint32 didnothing; /* number of do-nothing txns */ + +/* for mirror_mode */ +bool is_mirror_mode_on; /* true means mirror_mode=on */ + +/* static functions */ +static void checkarg(int argc, + char *argv[], + PGXC_NodeId *org_coordid, + char **host, + char **port); +static void help(const char *progname); + +/*------------------------------------------------------------------------- + * pgxc_clean + * + * option parameters: + * --all:recovery all coordinators + * --node:recovery coordinator number + * --username:USERNAME for connect to coordinator + * --password:PASSWORD for connect to coordinator + * + * exit code: + * 0: cleanup has been finished successfully + * 4: wrong arguement was specified in command line + * 6: pgxc_clean tried to connect to all running coordinators, but none + * of them accepts connection request + * 8: some kind of problem has occurred on GTM component + * 9: some kind of problem has occurred on xcm component + * 10: some kind of problem has occurred on coordinator component + * 11: some kind of problem has occurred on datanode component + * 12: pgxc_clean found transaction which has invalid status, such as + * committed on a node but aborted on another node + * 16: pgxc_clean encountered internal error, mostly out-of-memory + * + * notes + * - assume that node configuration is never changed + * -> If a node is added after invoking pgxc_clean, it will be ignored. + * -> If a node fails after invoking pgxc_clean, the failure will be + * detected by pgxc_clean and reported through exit code and log. + * - don't care lock about shared memory for xcm module, just use via API + *------------------------------------------------------------------------- + */ +int +main(int argc, char *argv[]) +{ + char *user = NULL; /* given username */ + char *passwd = NULL; /* given password */ + PGXC_NodeId org_coordid; /* given org coordid, 0 means all */ + PGXC_NodeId coordid; /* temporary coordid */ + + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgxc_clean")); + + /* initialize global variables */ + progname = get_progname(argv[0]); + all_coordinator_cnt = 0; + all_datanode_cnt = 0; + committed = 0; + aborted = 0; + didnothing = 0; + is_mirror_mode_on = false; + + /* check arguments */ + checkarg(argc, argv, &org_coordid, &user, &passwd); + dispmsg(lvl_debug, "%s start object coord=%u user=%s passwd=%s", + progname, org_coordid, user, passwd); + + /* get number of nodes, and status of each node */ + get_cluster_status(); + + /* originator node id must not exceed all_coordinator_cnt */ + if (org_coordid > all_coordinator_cnt) + { + fprintf(stderr, _("%s: NODE_NUMBER %u is out of range\n"), progname, + org_coordid); + exit(RESULT_ERR_ARGV); + } + + /* connect to a coordinator to execute queries */ + connect2coord(user, passwd); + + /* get mirror_mode in this cluster */ + get_mirror_mode(); + + /* connect to GTM */ + connect2gtm(); + + /* dump current snapshot for debug use */ + dump_snapshot(); + + /* + * Get list of 2PC-transactions which were originated on each coordinator, + * and clean them up. + */ + for (coordid = 1; coordid <= all_coordinator_cnt; coordid++) + { + int curr_txidx; /* current txn's index */ + + dispmsg(lvl_debug, "######## doing for originator %u.", coordid); + + /* Skip if originator was specified and this is not it. */ + if (org_coordid != 0 && org_coordid != coordid) + continue; + + /* initialize txinfo area */ + clear_txinfo(); + + /* Get list of transactions which were originated on the coordinator. */ + get_prepared_transactions(coordid); + + for (curr_txidx = 0; curr_txidx < txcnt; curr_txidx++) + { + int result; + + /* Get status of the transaction on each related node. */ + get_committed_transactions(curr_txidx); + + /* Cleanup the transaction */ + result = do_cleanup(curr_txidx); + switch (result) + { + case CLEANUP_COMMIT: + committed++; + break; + case CLEANUP_ROLLBACK: + aborted++; + break; + case CLEANUP_NOTHING: + didnothing++; + break; + case CLEANUP_SKIP: + /* We never reach here */ + break; + default: + break; + } + + } + } + + /* dump current snapshot for debug use */ + dump_snapshot(); + + /* Disconnect from coordinator */ + disconnect2coord(); + + /* Disconnect from GTM */ + disconnect2gtm(); + + /* Print summary of cleanup results. */ + dispmsg(lvl_info, + "cleanup finished: committed=%d aborted=%d did-nothing=%d", + committed, aborted, didnothing); + + exit(RESULT_SUCCESS); +} + + +/*------------------------------------------------------------------------- + * checkarg + * parse command line arguments and return settings through parameters. + * + * returns: + * N/A + *------------------------------------------------------------------------- + */ +static void +checkarg( + int argc, + char *argv[], + PGXC_NodeId *org_coordid, + char **user, + char **passwd) +{ + int c; + int optindex; + bool all_coordinators = false; /* --all/-a was specified */ + bool node_number = false; /* --node/-n was specified */ + static struct option long_options[] = { + {"all", no_argument, NULL, 'a'}, + {"node", required_argument, NULL, 'n'}, + {"username", required_argument, NULL, 'U'}, + {"password", required_argument, NULL, 'W'}, + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, '?'}, + {NULL, 0, NULL, 0} + }; + + while ((c = getopt_long(argc, argv, "an:U:W:V?", + long_options, &optindex)) != -1) + { + switch (c) + { + case 'a': + all_coordinators = true; + break; + case 'n': + /* check option parameters */ + /* -n NODE_NUMBER */ + /* NODE_NUMBER needs greater than 1 */ + node_number = true; + if (atoi(optarg) <= 0) + { + fprintf(stderr, _("%s: NODE_NUMBER needs greater than 0.\n"), + progname); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit(RESULT_ERR_ARGV); + } + *org_coordid = atoi(optarg); + break; + case 'U': + *user = optarg; + break; + case 'W': + *passwd = optarg; + break; + case 'V': + puts("pgxc_clean (PostgreSQL) " PG_VERSION); + exit(RESULT_SUCCESS); + break; + case '?': + if (strcmp(argv[optind - 1], "-?") == 0 || + strcmp(argv[optind - 1], "--help") == 0) + { + help(progname); + exit(RESULT_SUCCESS); + } + else + { + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(RESULT_ERR_ARGV); + } + break; + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(RESULT_ERR_ARGV); + break; + } + } + + /* receive user and password for libpq connection */ + if (argc > optind) + *user = strdup(argv[optind]); + if (argc > optind + 1) + *passwd = strdup(argv[optind + 1]); + if (argc > optind + 2) + { + fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), + progname, argv[optind + 2]); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit(RESULT_ERR_ARGV); + } + + /* --all and --node are exclusive */ + if (all_coordinators && node_number) + { + fprintf(stderr, _("%s: --all and --node can't be specified together.\n"), + progname); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit(RESULT_ERR_ARGV); + } + + /* + * We treat all transactions which were originated by all coordinators if + * --all is specified, or neither of --all nor --node was specified. + */ + if (all_coordinators || !node_number) + *org_coordid = 0; + + return; + +} + +/*------------------------------------------------------------------------- + * show help messages + *------------------------------------------------------------------------- + */ +static void +help(const char *progname) +{ + printf(_("%s is a utility to clean up 2PC-transactions.\n\n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTION]\n"), progname); + + printf(_("\nGeneral options:\n")); + printf(_(" -?, --help show this help, then exit\n")); + printf(_(" -V, --version output version information, then exit\n")); + + printf(_("\nOptions for originator:\n")); + printf(_(" -a, --all Clean up all transactions\n")); + printf(_(" -n, --node=NODE_NUMBER Clean up transactions originated on the Coordinator\n")); + + printf(_("\nConnection options:\n")); + printf(_(" -U, --username=USERNAME username used to connect to coordinator\n")); + printf(_(" -W, --password=PASSWORD password used to connect to coordinator\n")); + +} diff --git a/src/pgxc/pgxc_clean/pgxc_clean.h b/src/pgxc/pgxc_clean/pgxc_clean.h new file mode 100644 index 0000000..ae39eed --- /dev/null +++ b/src/pgxc/pgxc_clean/pgxc_clean.h @@ -0,0 +1,86 @@ +/*------------------------------------------------------------------------- + * + * pgxc_clean.h + * header file for the pgxc_clean + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#ifndef PGXC_CLEAN_H +#define PGXC_CLEAN_H + +#include "gtm/gtm_c.h" + +/* define program exit code */ +#define RESULT_SUCCESS 0 /* normal terminate */ +#define RESULT_ERR_ARGV 4 /* illegal format on option parameters */ +#define RESULT_ERR_CONN2COORD 6 /* couldn't connect to any coordinator */ +#define RESULT_ERR_GTM 8 /* failed to cooperate with GTM */ +#define RESULT_ERR_XCM 9 /* failed to cooperate with xcm */ +#define RESULT_ERR_COORD 10 /* failed to cooperate with coordinator */ +#define RESULT_ERR_DNODE 11 /* failed to cooperate with datanode */ +#define RESULT_ERR_TX_STATUS 12 /* transaction in invalid status found */ +#define RESULT_ERR_INTERNAL 16 /* pgxc_clean internal failure */ + +/* results of cleanup */ +#define CLEANUP_COMMIT 0 +#define CLEANUP_ROLLBACK 1 +#define CLEANUP_SKIP 2 +#define CLEANUP_NOTHING 3 + +/* define error level */ +typedef enum { + lvl_none = 0, + lvl_info, + lvl_warn, + lvl_error, + lvl_debug +} errlevel; + +/* + * Status of a datanode's mirror. + */ +typedef struct MirrorStatus { + PGXC_NodeId datanode_id; /* datanode id */ + int mirror_id; /* mirror id in the datanode */ + unsigned status; /* status of the mirror */ +} MirrorStatus; + +/* + * Status of each node. + * + * coordsts is allocated for all coordinators even if some of them failed. + * mirrorsts is allocated for all datanode mirrors even if some of them failed. + */ +extern unsigned *coordsts; +extern MirrorStatus *mirrorsts; + +/* prototypes */ +/* common.c */ +extern void dispmsg(errlevel el, const char *format, ...); + +/* subfunc.c */ +extern void get_mirror_mode(void); +extern void get_cluster_status(void); +extern void connect2coord(const char *user, const char *passwd); +extern void disconnect2coord(void); +extern void get_prepared_transactions(PGXC_NodeId org_coordid); +extern void get_committed_transactions(int txidx); +extern int do_cleanup(int txidx); +extern void clear_txinfo(void); + +/* gtm.c */ +void connect2gtm(void); +void remove_gxid_from_snapshot(GlobalTransactionId gxid, bool iscommit); +void disconnect2gtm(void); +#ifdef DEBUG +void dump_snapshot(void); +#else +#define dump_snapshot() +#endif + +#endif /* PGXC_CLEAN_H */ diff --git a/src/pgxc/pgxc_clean/subfunc.c b/src/pgxc/pgxc_clean/subfunc.c new file mode 100644 index 0000000..a194e04 --- /dev/null +++ b/src/pgxc/pgxc_clean/subfunc.c @@ -0,0 +1,986 @@ +/*------------------------------------------------------------------------- + * + * subfunc.c + * sub functions for pgxc_clean + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "gtm/gtm.h" +#include "gtm/gtm_txn.h" +#include "pgxc/xcm/node_membership.h" + +#include "pgxc_clean.h" +#include "txnctl.h" +#include "libpq-fe.h" + +/* + * SQL statement formats + */ + +/* SQL format for connected coordinator */ +#define SQLFMT_GETPREPAREDXACT "select * from pg_prepared_xact() where coordnum=%d;" +#define SQLFMT_ISCOMMITTED "select pgxc_is_committed('%u');" +#define SQLFMT_COMMIT "commit prepared '%s';" +#define SQLFMT_ROLLBACK "rollback prepared '%s';" + +/* EXECUTE DIRECT SQL format for un-connected coordinators */ +#define SQLFMT_EDC_GETPREPAREDXACT "EXECUTE DIRECT ON COORDINATOR %d 'select * from pg_prepared_xact() where coordnum=%d';" +#define SQLFMT_EDC_ISCOMMITTED "EXECUTE DIRECT ON COORDINATOR %d 'select pgxc_is_committed(''%u'')';" +#define SQLFMT_EDC_COMMIT "EXECUTE DIRECT ON COORDINATOR %d 'commit prepared ''%s''';" +#define SQLFMT_EDC_ROLLBACK "EXECUTE DIRECT ON COORDINATOR %d 'rollback prepared ''%s''';" + +/* EXECUTE DIRECT SQL format for datanodes */ +#define SQLFMT_EDD_GETPREPAREDXACT "EXECUTE DIRECT ON NODE %s 'select * from pg_prepared_xact() where coordnum=%d';" +#define SQLFMT_EDD_ISCOMMITTED "EXECUTE DIRECT ON NODE %s 'select pgxc_is_committed(''%u'')';" +#define SQLFMT_EDD_COMMIT "EXECUTE DIRECT ON NODE %s 'commit prepared ''%s''';" +#define SQLFMT_EDD_ROLLBACK "EXECUTE DIRECT ON NODE %s 'rollback prepared ''%s''';" + +/* Get mirror_mode from connected coordinator */ +#define SQLFMT_SHOWMIRRORMODE "show mirror_mode;" + +/* + * EXECUTE DIRECT can't invoked COMMIT/ABORT PREPARED on the coordinator + * which pgxc_clean connected directly. So we have to use two connections, + * one is established without "remotetype" option for EXECUTE DIRECT on nodes + * other than connected coordinator, and another is established with + * "remotetype=coordinator" option for invoke transaction management commands + * on the connected coordinator. + */ +PGXC_NodeId con_coordid; /* id of connected coordinator */ +PGconn *conn_coord; /* connection for the coordinator */ +PGconn *conn_other; /* connection for other nodes */ + +extern bool is_mirror_mode_on; /* true means mirror_mode=on */ + +extern int all_coordinator_cnt; /* number of coords in cluster */ +extern int all_datanode_cnt; /* number of dnodes in cluster */ +extern int all_mirror_cnt; /* number of datanode mirrors in cluster */ + +/* static functions */ +static void get_nodests(void); +static bool contains_tx_sts(prepared_txninfo *txinfo, NODE_STS sts); +static void cleanup_txn(prepared_txninfo *txinfo, bool iscommit); + +/* + * get_mirror_mode + * get cluster's mirror_mode. + */ +void +get_mirror_mode(void) +{ + PGresult *res; + dispmsg(lvl_debug, "BEGIN: %s()", __FUNCTION__); + + /* + * Execute query to get mirror_mode. + */ + res = PQexec(conn_coord, SQLFMT_SHOWMIRRORMODE); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn_coord); + dispmsg(lvl_error, + "couldn't get mirror_mode: %s", emsg); + PQclear(res); + exit(RESULT_ERR_COORD); + } + + is_mirror_mode_on = (strcmp(PQgetvalue(res, 0, 0), "on") == 0); + PQclear(res); + + dispmsg(lvl_debug, "mirror_mode=%s", is_mirror_mode_on ? "on" : "off"); +} + +/* + * get_cluster_status + * get cluster configuration and status of each node in the cluster. + */ +void +get_cluster_status(void) +{ + int nRet; + + dispmsg(lvl_debug, "BEGIN: get_cluster_status()"); + + /* get number of coordinators from xcm */ + nRet = get_xcm_coordinator_count(&all_coordinator_cnt); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, + "couldn't get number of coordinators in the cluster.(%d)", nRet); + exit(RESULT_ERR_XCM); + } + dispmsg(lvl_debug, "number of coordinators is %d", all_coordinator_cnt); + + /* get number of datanodes from xcm */ + nRet = get_xcm_datanode_count(&all_datanode_cnt); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, + "couldn't get number of datanodes in the cluster.(%d)", nRet); + exit(RESULT_ERR_XCM); + } + dispmsg(lvl_debug, "number of datanodes is %d", all_datanode_cnt); + + /* get running status of all coordinators and datanodes */ + get_nodests(); +} + + +/*------------------------------------------------------------------------- + * connect2coord + * connect to a running coordinator in the cluster which has minimum id. + * + * returns: + * node id of connected coordinator, or 0 if all coordinator have failed. + *------------------------------------------------------------------------- + */ +void +connect2coord(const char *user, const char *passwd) +{ + int nRet; + int nconns = 0; + xcm_connPoint *xcwconn; + char port[10]; + int cdidx; + + dispmsg(lvl_debug, "BEGIN: connect2coord(%s, %s)", user, passwd); + + /* Try all coordinator in order of id */ + for (cdidx = 0; cdidx < all_coordinator_cnt; cdidx++) + { + dispmsg(lvl_debug, + "trying to connect to coordinator %d", + cdidx + 1); + + /* Ignore failed coordinators */ + if (XCM_IS_FAULT(coordsts[cdidx])) + continue; + + /* Get connection information from xcm module. */ + /* XXX: Should we use connection points other than first one? */ + nRet = get_xcm_coordinator_connPoints(cdidx + 1, &nconns, &xcwconn); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, + "couldn't get connection point for coordinator %u", + cdidx + 1); + exit(RESULT_ERR_XCM); + } + + /* Convert port number to string */ + snprintf(port, sizeof(port), "%d", xcwconn->port); + + /* + * Connect to coordinator with remotetype option. This connection is + * used to execute ordinary query statements on the connected + * coordinator directly. + */ + conn_coord = PQsetdbLogin(xcwconn->addr, + port, + "-c remotetype=coordinator", + NULL, + "template1", + user, + passwd); + if (!conn_coord || PQstatus(conn_coord) != CONNECTION_OK) + { + dispmsg(lvl_warn, + "couldn't connect to coordinator %u with remotetype: %s", + cdidx + 1, + PQerrorMessage(conn_coord)); + PQfinish(conn_coord); + free_xcm_connPoints(xcwconn, nconns); + continue; + } + + /* + * Connect to coordinator with remotetype option. This connection is + * used to execute EXECUTE DIRECT statements on the node other than + * connected coordinator. + */ + conn_other = PQsetdbLogin(xcwconn->addr, + port, + NULL, + NULL, + "template1", + user, + passwd); + if (!conn_other || PQstatus(conn_other) != CONNECTION_OK) + { + dispmsg(lvl_warn, + "couldn't connect to coordinator %u without remotetype: %s", + cdidx + 1, + PQerrorMessage(conn_other)); + PQfinish(conn_coord); + PQfinish(conn_other); + free_xcm_connPoints(xcwconn, nconns); + continue; + } + + free_xcm_connPoints(xcwconn, nconns); + + /* Now we have two connections against a coordinator for cleanup. */ + con_coordid = cdidx + 1; + dispmsg(lvl_debug, "connected to coordinator %u", con_coordid); + + return; + } + + /* failed to establish connections against coordinator */ + dispmsg(lvl_error, "there is no running coordinator"); + exit(RESULT_ERR_CONN2COORD); +} + +void +disconnect2coord(void) +{ + PQfinish(conn_coord); + PQfinish(conn_other); +} + +/*------------------------------------------------------------------------- + * get_prepared_transactions + * Get list of 2PC-transactions which is prepared on any node. + *------------------------------------------------------------------------- + */ +void +get_prepared_transactions(PGXC_NodeId org_coordid) +{ + int nodeloop, txidx; + + dispmsg(lvl_debug, + "BEGIN: get_prepared_transactions(org_coordid=%u)", + org_coordid); + + /* + * Get list of prepared transactions from each coordinator with + * invoking pg_prepared_xact() and merge them into one list. + */ + for (nodeloop = 0; nodeloop < all_coordinator_cnt; nodeloop++) + { + PGXC_NodeId nodeid = (PGXC_NodeId) (nodeloop + 1); + PGresult *res; + char sql[512]; + bool on_connected_node = (nodeid == con_coordid); + PGconn *conn = on_connected_node ? conn_coord : conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(coordsts[nodeloop])) + continue; + + /* Construct query for pg_prepared_xact(). */ + if (on_connected_node) + snprintf(sql, sizeof(sql), SQLFMT_GETPREPAREDXACT, org_coordid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDC_GETPREPAREDXACT, nodeid, + org_coordid); + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* + * Execute query to get list of transactions which have been prepared + * on the node. + */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "pg_prepared_xact() failed on coordinator %u for originator %u :%s", + nodeid, org_coordid, emsg); + PQclear(res); + exit(RESULT_ERR_COORD); + } + + /* store transaction status into the list */ + for (txidx = 0; txidx < PQntuples(res); txidx++) + { + TransactionId transaction; + bool isddl; + bool isimplicit; + + transaction = (TransactionId) atoi(PQgetvalue(res, txidx, 0)); + isddl = (strcmp(PQgetvalue(res, txidx, 5), "t") == 0); + isimplicit = (strcmp(PQgetvalue(res, txidx, 6), "t") == 0); + + set_txinfo( + org_coordid, /* originator coordinator id */ + true, /* True if source was coordinator */ + nodeid, /* nodeid */ + 0, /* mirror_id, 0 if iscoord */ + transaction, /* transaction */ + PQgetvalue(res, txidx, 1), /* gid */ + isddl, /* is_ddl */ + isimplicit, /* is_implicit */ + PQgetvalue(res, txidx, 8)); /* nodelist */ + + } + + PQclear(res); + } + + /* + * Get list of prepared transactions from each datanode with + * invoking pg_prepared_xact() and merge them into one list. + */ + for (nodeloop = 0; nodeloop < all_mirror_cnt; nodeloop++) + { + PGXC_NodeId nodeid = mirrorsts[nodeloop].datanode_id; + int mirror_id = mirrorsts[nodeloop].mirror_id; + PGresult *res; + char sql[512]; + char dnodestr[64]; + PGconn *conn = conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(mirrorsts[nodeloop].status)) + continue; + + /* Set datanode id */ + if (is_mirror_mode_on) + snprintf(dnodestr, sizeof(dnodestr), "%u/%d", nodeid, mirror_id); + else + snprintf(dnodestr, sizeof(dnodestr), "%u", nodeid); + + /* Construct EXECUTE DIRECT query for pg_prepared_xact(). */ + snprintf(sql, sizeof(sql), SQLFMT_EDD_GETPREPAREDXACT, + dnodestr, org_coordid); + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute query to get list of prepared transactions. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "pg_prepared_xact() failed on datanode %s for originator %u :%s", + dnodestr, org_coordid, emsg); + PQclear(res); + exit(RESULT_ERR_DNODE); + } + + /* store transaction status into the list */ + for (txidx = 0; txidx < PQntuples(res); txidx++) + { + TransactionId transaction; + bool isddl; + bool isimplicit; + + transaction = (TransactionId) atoi(PQgetvalue(res, txidx, 0)); + isddl = (strcmp(PQgetvalue(res, txidx, 5), "t") == 0); + isimplicit = (strcmp(PQgetvalue(res, txidx, 6), "t") == 0); + + set_txinfo( + org_coordid, /* originator coordinator id */ + false, /* true if source was coordinator */ + nodeid, /* nodeid */ + mirror_id, /* mirror_id, 0 if iscoord */ + transaction, /* transaction */ + PQgetvalue(res, txidx, 1), /* gid */ + isddl, /* is_ddl */ + isimplicit, /* is_implicit */ + PQgetvalue(res, txidx, 8)); /* nodelist */ + + } + + PQclear(res); + + } + + /* for debug use */ +#ifdef DEBUG + for(txidx = 0; txidx < txcnt; txidx++) + dump_txinfo(txidx); +#endif + + return; +} + +/*------------------------------------------------------------------------- + * get_committed_transactions + * update status of a transaction on a node to COMMITTED or ABORTED + * whose status has not been clarified. + *------------------------------------------------------------------------- + */ +void +get_committed_transactions(int txidx) +{ + int nodeidx; + prepared_txninfo *txinfo = NULL; + + dispmsg(lvl_debug, "BEGIN: get_committed_transactions(%d)", txidx); + + /* get prepared_txninfo */ + txinfo = get_prepared_txninfo(txidx); + if (!txinfo) + { + dispmsg(lvl_error, "couldn't get prepared transaction info."); + exit(RESULT_ERR_INTERNAL); + } + + /* coordinators */ + for (nodeidx = 0; nodeidx < all_coordinator_cnt; nodeidx++) + { + PGXC_NodeId nodeid = (PGXC_NodeId) (nodeidx + 1); + PGresult *res; + char sql[1024]; + bool on_connected_node = (nodeid == con_coordid); + PGconn *conn = on_connected_node ? conn_coord : conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(coordsts[nodeidx])) + continue; + + /* Ignore node whose status has been already known */ + if (txinfo->tx_sts_c[nodeidx] != STS_RELATED) + continue; + + /* Determine which connection should be used. */ + if (nodeid == con_coordid) + conn = conn_coord; + else + conn = conn_other; + + /* Construct EXECUTE DIRECT query for pgxc_is_committed(). */ + if (nodeid == con_coordid) + snprintf(sql, sizeof(sql), SQLFMT_ISCOMMITTED, txinfo->txid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDC_ISCOMMITTED, + nodeid, txinfo->txid); + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute query to get is committed transaction. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "pgxc_is_committed() failed on coordinator %u for transaction %s: %s", + nodeid, txinfo->gid, emsg); + + PQclear(res); + exit(RESULT_ERR_COORD); + } + + /* update status */ + if (strcmp(PQgetvalue(res, 0, 0), "t") == 0) + set_tx_sts(txinfo, true, nodeid, 0, STS_COMMITTED); + else + set_tx_sts(txinfo, true, nodeid, 0, STS_ABORTED); + + PQclear(res); + } + + /* datanodes */ + for (nodeidx = 0; nodeidx < all_mirror_cnt; nodeidx++) + { + PGXC_NodeId nodeid = mirrorsts[nodeidx].datanode_id; + int mirror_id = mirrorsts[nodeidx].mirror_id; + PGresult *res; + char sql[512]; + char dnodestr[64]; + PGconn *conn = conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(mirrorsts[nodeidx].status)) + continue; + + if (txinfo->tx_sts_m[nodeidx] == STS_RELATED) + { + /* Set datanode id */ + if (is_mirror_mode_on) + snprintf(dnodestr, sizeof(dnodestr), "%u/%d", nodeid, mirror_id); + else + snprintf(dnodestr, sizeof(dnodestr), "%u", nodeid); + + /* Construct EXECUTE DIRECT query for pgxc_is_committed(). */ + snprintf(sql, sizeof(sql), SQLFMT_EDD_ISCOMMITTED, dnodestr, txinfo->txid); + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute query to get is committed transaction. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_TUPLES_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "pgxc_is_committed() failed on datanode %s for transaction %s: %s", + dnodestr, txinfo->gid, emsg); + PQclear(res); + exit(RESULT_ERR_DNODE); + } + + /* update status */ + if (strcmp(PQgetvalue(res, 0, 0), "t") == 0) + set_tx_sts(txinfo, false, nodeid, mirror_id, STS_COMMITTED); + else + set_tx_sts(txinfo, false, nodeid, mirror_id, STS_ABORTED); + + PQclear(res); + } + } + + /* for debug use, removed on release build */ + dump_txinfo(txidx); +} + +/*------------------------------------------------------------------------- + * do_cleanup + * cleanup prepared transactions on each node along the status of the + * global transaction + *------------------------------------------------------------------------- + */ +int +do_cleanup(int txidx) +{ + prepared_txninfo *txinfo = NULL; + bool is_related, is_committed, is_aborted; + + dispmsg(lvl_debug, "BEGIN: do_cleanup(%d)", txidx); + + /* get prepared_txninfo */ + txinfo = get_prepared_txninfo(txidx); + if (!txinfo) + { + dispmsg(lvl_error, "couldn't get prepared transaction info."); + exit(RESULT_ERR_INTERNAL); + } + + /* get txn-status on each node */ + is_related = contains_tx_sts(txinfo, STS_RELATED); + is_committed = contains_tx_sts(txinfo, STS_COMMITTED); + is_aborted = contains_tx_sts(txinfo, STS_ABORTED); + + /* + * 1. RELATED node is contained(in-Prepare) + * + * 1-1. COMMITTED node is contained ==> illegal txn-condition + * 1-2. ABORTED node is contained ==> illegal txn-condition + * 1-3. otherwise ==> need rollback on prepared-node + */ + if (is_related) + { + /* + * If there are COMMITTED-node or ABORTED-node (or both), the transaction + * condition is wrong. + * Because transaction is not complete prepare-transaction. + */ + if(is_committed || is_aborted) + { + dispmsg(lvl_error, + "transaction(%d:%s) is bad condition. coord[%.*s] dnode[%.*s]", + txinfo->txid, txinfo->gid, all_coordinator_cnt, txinfo->tx_sts_c, + all_mirror_cnt, txinfo->tx_sts_m); + + exit(RESULT_ERR_TX_STATUS); + } + + /* + * The transaction is 'in-Prepare' condition. + * In this case, need to rollback transaction on PREPARED-node. + * XXX: We should do nothing if all node was prepared, shouldn't we? + */ + cleanup_txn(txinfo, false); + + /* Remove gid from GTM if the transaction was explicit-2PC */ + if (!txinfo->isimplicit) + remove_gxid_from_snapshot(txinfo->txid, false); + + return CLEANUP_ROLLBACK; + } + + /* + * A transaction which has critical contradiction was found, give + * up whole job. + */ + if (is_committed && is_aborted) + { + dispmsg(lvl_error, + "transaction(%d:%s) is bad condition. coord[%.*s] dnode[%.*s]", + txinfo->txid, txinfo->gid, all_coordinator_cnt, txinfo->tx_sts_c, + all_mirror_cnt, txinfo->tx_sts_m); + + exit(RESULT_ERR_TX_STATUS); + } + + /* + * 3. COMMITTED nodes only + * ==> need commit + */ + if (is_committed) + { + cleanup_txn(txinfo, true); + + /* Remove gid from GTM if the transaction was explicit-2PC */ + if (!txinfo->isimplicit) + remove_gxid_from_snapshot(txinfo->txid, true); + + return CLEANUP_COMMIT; + } + + /* + * 4. ABORTED nodes only + * ==> need rollback + */ + if (is_aborted) + { + cleanup_txn(txinfo, false); + + /* Remove gid from GTM if the transaction was explicit-2PC */ + if (!txinfo->isimplicit) + remove_gxid_from_snapshot(txinfo->txid, false); + + return CLEANUP_ROLLBACK; + } + + /* + * 5. PREPARED nodes only + * + * 5-1. implicit2PC transaction ==> need commit + * 5-2. explicit2PC transaction ==> do nothing + */ + if (!txinfo->isimplicit) + { + dispmsg(lvl_info, "do nothing."); + return CLEANUP_NOTHING; + } + + /* + * If no commit or abort are execurted, commit in all the involved + * nodes because it is obvious that the transaction was intended to + * be committed. + */ + cleanup_txn(txinfo, true); + + return CLEANUP_COMMIT; +} + +/*------------------------------------------------------------------------ + * clear_txinfo + * clear list of transaction and initialize it + *------------------------------------------------------------------------ + */ +void +clear_txinfo(void) +{ + dispmsg(lvl_debug, "BEGIN: clear_txinfo()"); + init_txinfo(); +} + +/*------------------------------------------------------------------------ + * static functions + *------------------------------------------------------------------------ + */ +/*------------------------------------------------------------------------ + * get_nodests + * get status of all nodes in the cluster + * + * Note: all_coordinator_cnt and all_datanode_cnt MUST be set before + * calling this function. + *------------------------------------------------------------------------ + */ +static void +get_nodests(void) +{ + int nodeloop; + int nRet; + MirrorStatus *mirror; + int failed_cnt; + + dispmsg(lvl_debug, "BEGIN: get_nodests()"); + + /* coordinators */ + /* malloc for sts area */ + coordsts = (unsigned *) malloc(sizeof(unsigned) * all_coordinator_cnt); + if (!coordsts) + { + dispmsg(lvl_error, "couldn't allocate memory for coordsts.(%d)", errno); + exit(RESULT_ERR_INTERNAL); + } + + /* get status of each coordinator from xcm */ + failed_cnt = 0; + for (nodeloop = 0; nodeloop < all_coordinator_cnt; nodeloop++) + { + nRet = get_xcm_coordinator_status(nodeloop + 1, &coordsts[nodeloop]); + if (nRet != XCM_OK && nRet != XCM_ERR_COMP_FAILED) + { + dispmsg(lvl_error, "couldn't get status of coord(%d).(%d)", + nodeloop + 1, nRet); + exit(RESULT_ERR_XCM); + } + failed_cnt += (nRet != XCM_OK); + dispmsg(lvl_debug, "status of coordinator %d is %d", nodeloop + 1, + coordsts[nodeloop]); + } + + /* + * If over half of coordinators have failed, it can be said that the whole + * cluster has failed, so we might give up to cleanup. + * Discussed on Feb 8, 2011. + */ + if (failed_cnt > all_coordinator_cnt / 2) + { + dispmsg(lvl_error, "too many coordinators failed (%d/%d)", + failed_cnt, all_coordinator_cnt); + exit(RESULT_ERR_COORD); + } + + /* count all datanode mirrors */ + all_mirror_cnt = 0; + for (nodeloop = 0; nodeloop < all_datanode_cnt; nodeloop++) + { + int mirror_cnt; + + nRet = get_xcm_mirror_count(nodeloop + 1, &mirror_cnt); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, "couldn't get mirror count of datanode %d.(%d)", + nodeloop + 1, nRet); + exit(RESULT_ERR_XCM); + } + + all_mirror_cnt += mirror_cnt; + } + + /* allocate array of MirrorStatus for all of datanode mirrors */ + mirrorsts = (MirrorStatus *) malloc(sizeof(MirrorStatus) * all_mirror_cnt); + if (!mirrorsts) + { + dispmsg(lvl_error, "couldn't allocate memory for mirrorsts.(%d)", + errno); + exit(RESULT_ERR_INTERNAL); + } + + /* get status of each datanode mirror from xcm and store into mirrorsts */ + failed_cnt = 0; + mirror = mirrorsts; + for (nodeloop = 0; nodeloop < all_datanode_cnt; nodeloop++) + { + int mirrorcnt; + int mirrorloop; + char dnodestr[32]; + + nRet = get_xcm_mirror_count(nodeloop + 1, &mirrorcnt); + if (nRet != XCM_OK) + { + dispmsg(lvl_error, "couldn't get mirror count of datanode %d.(%d)", + nodeloop + 1, nRet); + exit(RESULT_ERR_XCM); + } + + for (mirrorloop = 0; mirrorloop < mirrorcnt; mirrorloop++) + { + mirror->datanode_id = nodeloop + 1; + mirror->mirror_id = mirrorloop + 1; + + /* Set datanode id */ + if (is_mirror_mode_on) + snprintf(dnodestr, sizeof(dnodestr), "%u/%d", mirror->datanode_id, mirror->mirror_id); + else + snprintf(dnodestr, sizeof(dnodestr), "%u", mirror->datanode_id); + + nRet = get_xcm_mirror_status(mirror->datanode_id, + mirror->mirror_id, + &mirror->status); + if (nRet != XCM_OK && nRet != XCM_ERR_COMP_FAILED) + { + dispmsg(lvl_error, "couldn't get status of datanode %s.(%d)", dnodestr, nRet); + free(coordsts); + free(mirrorsts); + exit(RESULT_ERR_XCM); + } + failed_cnt += (nRet != XCM_OK); + dispmsg(lvl_debug, "status of datanode %s is %d", dnodestr, mirror->status); + + mirror++; + } + } + + /* + * If over half of datanodes have failed, it can be said that the whole + * cluster has failed, so we might give up to cleanup. + * Discussed on Feb 8, 2011. + */ + if (failed_cnt > all_mirror_cnt / 2) + { + dispmsg(lvl_error, "too many datanodes failed (%d/%d)", + failed_cnt, all_mirror_cnt); + exit(RESULT_ERR_DNODE); + } + + return; +} + +/*------------------------------------------------------------------------- + * when transaction contains sts returns true + *------------------------------------------------------------------------- + */ +static bool +contains_tx_sts(prepared_txninfo *txinfo, NODE_STS sts) +{ + int nodeidx; + + if (!txinfo) + return false; + + /* coordinators */ + for (nodeidx = 0; nodeidx < all_coordinator_cnt; nodeidx++) + { + if (txinfo->tx_sts_c[nodeidx] == sts) + return true; + } + + /* datanodes */ + for (nodeidx = 0; nodeidx < all_mirror_cnt; nodeidx++) + { + if (txinfo->tx_sts_m[nodeidx] == sts) + return true; + } + + return false; +} + +/*------------------------------------------------------------------------- + * commit or rollback transaction on prepared node + *------------------------------------------------------------------------- + */ +static void +cleanup_txn(prepared_txninfo *txinfo, bool iscommit) +{ + int nodeidx; + char sql[512]; + PGresult *res; + uint32 coord_committed = 0; /* # of committed coordinators */ + uint32 coord_aborted = 0; /* # of aborted coordinators */ + uint32 dnode_committed = 0; /* # of committed datanodes */ + uint32 dnode_aborted = 0; /* # of aborted datanodes */ + + dispmsg(lvl_debug, "BEGIN: cleanup_txn(txid=%u, %s)", + txinfo ? txinfo->txid : 0, + iscommit ? "commit" : "rollback"); + + /* null pointer */ + if (!txinfo) + exit(RESULT_ERR_INTERNAL); + + /* coordinators */ + for (nodeidx = 0; nodeidx < all_coordinator_cnt; nodeidx++) + { + PGXC_NodeId nodeid = (PGXC_NodeId) (nodeidx + 1); + bool on_connected_node = (nodeid == con_coordid); + PGconn *conn = on_connected_node ? conn_coord : conn_other; + + /* Ignore failed components */ + if (XCM_IS_FAULT(coordsts[nodeidx])) + continue; + + if (txinfo->tx_sts_c[nodeidx] == STS_PREPARED) + { + /* Construct EXECUTE DIRECT for commit. */ + if (iscommit) + { + if (on_connected_node) + snprintf(sql, sizeof(sql), SQLFMT_COMMIT, txinfo->gid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDC_COMMIT, + nodeid, txinfo->gid); + } + else + { + if (on_connected_node) + snprintf(sql, sizeof(sql), SQLFMT_ROLLBACK, txinfo->gid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDC_ROLLBACK, + nodeid, txinfo->gid); + } + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute commit or rollback prepared transaction. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "couldn't %s on coordinator %u for cleanup transaction %s: %s", + iscommit ? "COMMIT" : "ABORT", nodeid, txinfo->gid, + emsg); + PQclear(res); + exit(RESULT_ERR_COORD); + } + + if (iscommit) + coord_committed++; + else + coord_aborted++; + + PQclear(res); + } + } + + /* datanodes */ + for (nodeidx = 0; nodeidx < all_mirror_cnt; nodeidx++) + { + PGXC_NodeId nodeid = mirrorsts[nodeidx].datanode_id; + int mirror_id = mirrorsts[nodeidx].mirror_id; + PGconn *conn = conn_other; + char dnodestr[64]; + + /* Ignore failed components */ + if (XCM_IS_FAULT(mirrorsts[nodeidx].status)) + continue; + + if (txinfo->tx_sts_m[nodeidx] == STS_PREPARED) + { + /* Set datanode id */ + if (is_mirror_mode_on) + snprintf(dnodestr, sizeof(dnodestr), "%u/%d", nodeid, mirror_id); + else + snprintf(dnodestr, sizeof(dnodestr), "%u", nodeid); + + /* Construct EXECUTE DIRECT for commit. */ + if (iscommit) + snprintf(sql, sizeof(sql), SQLFMT_EDD_COMMIT, + dnodestr, txinfo->gid); + else + snprintf(sql, sizeof(sql), SQLFMT_EDD_ROLLBACK, + dnodestr, txinfo->gid); + + dispmsg(lvl_debug, "SQL=[%s]", sql); + + /* Execute commit or rollback prepared transaction. */ + res = PQexec(conn, sql); + if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) + { + char *emsg = PQerrorMessage(conn); + dispmsg(lvl_error, + "couldn't %s on datanode %s for cleanup transaction %s: %s", + iscommit ? "COMMIT" : "ABORT", dnodestr, txinfo->gid, emsg); + PQclear(res); + exit(RESULT_ERR_DNODE); + } + + if (iscommit) + dnode_committed++; + else + dnode_aborted++; + + PQclear(res); + } + } + + if (iscommit) + dispmsg(lvl_info, "txid=%u coordinator=%u datanode=%u", + txinfo->txid, coord_committed, dnode_committed); + else + dispmsg(lvl_info, "txid=%u coordinator=%u datanode=%u", + txinfo->txid, coord_aborted, dnode_aborted); +} diff --git a/src/pgxc/pgxc_clean/txnctl.c b/src/pgxc/pgxc_clean/txnctl.c new file mode 100644 index 0000000..cc34a3c --- /dev/null +++ b/src/pgxc/pgxc_clean/txnctl.c @@ -0,0 +1,495 @@ +/*------------------------------------------------------------------------- + * + * txnctl.c + * control for transaction information + * + * Portions Copyright (c) 2011 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include <string.h> + +#include "gtm/gtm_c.h" +#include "access/gtm.h" +#include "pgxc/xcm/node_membership.h" + +#include "pgxc_clean.h" +#include "txnctl.h" + +/* Global variables */ +/* external */ +extern int prepared_txcnt; /* number of prepared transactions */ +extern int all_coordinator_cnt; /* number of coords in cluster */ +extern int all_datanode_cnt; /* number of dnodes in cluster */ +extern int all_mirror_cnt; /* number of mirrors in cluster */ +extern bool is_mirror_mode_on; /* true means mirror_mode=on */ +/* status of each node */ +extern unsigned *coordsts; /* status of each coordinator */ +extern MirrorStatus *mirrorsts; /* status of each datanode mirrors */ + +/* private */ +prepared_txninfo **txinfo; /* transaction information structure */ +int txcnt; /* number of registered transactions */ +int malloccnt; /* number of allocated memory */ + +/* private functions */ +static void set_mirrorsts(const char *nodelist, prepared_txninfo *tx, bool iscoord); +static void add_txinfo_area(void); + +/* + * Create new prepared_txninfo entry with given information. + */ +static prepared_txninfo * +create_prepared_txninfo( + PGXC_NodeId org_coordid, + bool iscoord, + PGXC_NodeId nodeid, + TransactionId txid, + char *gid, + bool isddl, + bool isimplicit, + char *nodelist) +{ + prepared_txninfo *mytx; + NODE_STS *coords = NULL; + NODE_STS *mirrors = NULL; + int nodeloop; + + /* + * New transaction was found, allocate memory for one transaction + * information. + */ + mytx = (prepared_txninfo *) calloc(1, sizeof(prepared_txninfo)); + if (!mytx) + { + dispmsg(lvl_error, + "couldn't allocate memory for transaction information.(%d)", + errno); + exit(RESULT_ERR_INTERNAL); + } + + /* Initialize the entry */ + mytx->org_coordid = org_coordid; + mytx->txid = txid; + mytx->gid = strdup(gid); + if (!mytx->gid) + { + dispmsg(lvl_error, "couldn't allocate memory for gid.(%d)", errno); + exit(RESULT_ERR_INTERNAL); + } + mytx->isddl = isddl; + mytx->isimplicit = isimplicit; + mytx->nodelist = strdup(nodelist); /* XXX: necessary? */ + if (!mytx->nodelist) + { + dispmsg(lvl_error, "couldn't allocate memory for nodelist.(%d)", + errno); + exit(RESULT_ERR_INTERNAL); + } + mytx->tx_sts_c = NULL; + mytx->tx_sts_m = NULL; + + /* + * Allocate status-array for all coordinators in the cluster, though we + * care coordinators only when a transaction includes DDL. + */ + coords = (NODE_STS *) malloc(sizeof(NODE_STS) * all_coordinator_cnt); + if (!coords) + { + dispmsg(lvl_error, + "couldn't allocate memory for coordnode sts.(%d)", errno); + exit(RESULT_ERR_INTERNAL); + } + for (nodeloop = 0; nodeloop < all_coordinator_cnt; nodeloop++) + { + if ( XCM_IS_FAULT(coordsts[nodeloop]) ) + coords[nodeloop] = STS_FAILED; + else + coords[nodeloop] = STS_UNKNOWN; + } + mytx->tx_sts_c = coords; + + /* + * Allocate status-array for all datanode mirrors in the cluster. + */ + mirrors = (NODE_STS *) malloc(sizeof(NODE_STS) * all_mirror_cnt); + if (!mirrors) + { + dispmsg(lvl_error, + "couldn't allocate memory for datanode sts.(%d)", errno); + exit(RESULT_ERR_INTERNAL); + } + for (nodeloop = 0; nodeloop < all_mirror_cnt; nodeloop++) + { + if (XCM_IS_FAULT(mirrorsts[nodeloop].status)) + mirrors[nodeloop] = STS_FAILED; + else + mirrors[nodeloop] = STS_UNKNOWN; + } + mytx->tx_sts_m = mirrors; + + return mytx; +} + +/*------------------------------------------------------------------------- + * set_txinfo + * store transaction information gotten from a node into transaction list. + * + * parameters: + * PGXC_NodeId org_coordid:çºè¡å coordid + * bool iscoord: True if the source is a coordinator + * PGXC_NodeId nodeid: id of source node + * TransactionId txid:pg_prepared_xact().transaction + * char *gid:pg_prepared_xact().gid + * bool isddl:pg_prepared_xact().is_ddl + * bool isimplicit:pg_prepared_xact().is_implicit + * char *nodelist:pg_prepared_xact().nodelist + * + * returns: + * N/A + *------------------------------------------------------------------------- + */ +void +set_txinfo( + PGXC_NodeId org_coordid, + bool iscoord, + PGXC_NodeId nodeid, + int mirror_id, + TransactionId txid, + char *gid, + bool isddl, + bool isimplicit, + char *nodelist) + +{ + prepared_txninfo *mytx = NULL; + + dispmsg(lvl_debug, "BEGIN: set_txinfo(%d, %s, %u, %d, %u, %s, %s, %s, %s)", + org_coordid, iscoord ? "TRUE" : "FALSE", nodeid, mirror_id, txid, + gid, isddl ? "TRUE" : "FALSE", isimplicit ? "TRUE" : "FALSE", nodelist); + + /* + * If this transaction has not been stored yet, create new transaction + * entry for it. + */ + mytx = get_tx(txid); + if (mytx == NULL) + { + /* Create entry for newly found transaction */ + mytx = create_prepared_txninfo(org_coordid, iscoord, nodeid, txid, gid, + isddl, isimplicit, nodelist); + + /* Expand transaction slot if necessary */ + if (txcnt == malloccnt) + add_txinfo_area(); + + /* store the transaction into transaction list */ + txinfo[txcnt++] = mytx; + } + + /* All coordinators are related node when isddl was true */ + if (mytx->isddl) + { + int coordidx; + + for (coordidx = 0; coordidx < all_coordinator_cnt; coordidx++) + if (mytx->tx_sts_c[coordidx] == STS_UNKNOWN) + mytx->tx_sts_c[coordidx] = STS_RELATED; + } + + /* set status of related datanode to RELATED */ + set_mirrorsts(nodelist, mytx, iscoord); + + /* + * The status of the transaction on the source node is PREPARED, because + * pg_prepared_xact() entry was found on the node. + */ + set_tx_sts(mytx, iscoord, nodeid, mirror_id, STS_PREPARED); + + return; +} + +/*------------------------------------------------------------------------- + * initialize transaction information + *------------------------------------------------------------------------- + */ +void +init_txinfo(void) +{ + dispmsg(lvl_debug, "BEGIN: init_txinfo()"); + + if (txinfo) + { + int txidx; + + for (txidx = 0; txidx < txcnt; txidx++) + { + free(txinfo[txidx]->gid); + free(txinfo[txidx]->nodelist); + free(txinfo[txidx]->tx_sts_c); + free(txinfo[txidx]->tx_sts_m); + free(txinfo[txidx]); + } + free(txinfo); + txinfo = NULL; + } + malloccnt = 0; + txcnt = 0; +} + +/*------------------------------------------------------------------------- + * dump transaction information + *------------------------------------------------------------------------- + */ +#ifdef DEBUG +void +dump_txinfo(int txidx) +{ + dispmsg(lvl_debug, "BEGIN: dump_txinfo(%d/%d)", txidx + 1, txcnt); + + printf("txinfo[%d]=%p\n", txidx, txinfo[txidx]); + + printf("[%d]org_coordid=%d(%p)\n", + txidx, txinfo[txidx]->org_coordid, &txinfo[txidx]->org_coordid); + printf("[%d]txid=%d(%p)\n", + txidx, txinfo[txidx]->txid, &txinfo[txidx]->txid); + printf("[%d]gid=[%s](%p)\n", + txidx, txinfo[txidx]->gid, txinfo[txidx]->gid); + printf("[%d]isddl=%s(%p)\n", + txidx, txinfo[txidx]->isddl ? "TRUE" : "FALSE", &txinfo[txidx]->isddl); + printf("[%d]isimplicit=%s(%p)\n", + txidx, txinfo[txidx]->isimplicit ? "TRUE" : "FALSE", &txinfo[txidx]->isimplicit); + printf("[%d]nodelist=[%s](%p)\n", + txidx, txinfo[txidx]->nodelist, txinfo[txidx]->nodelist); + printf("[%d]tx_sts_c=[%.*s](%p)\n", + txidx, all_coordinator_cnt, txinfo[txidx]->tx_sts_c, txinfo[txidx]->tx_sts_c); + printf("[%d]tx_sts_m=[%.*s](%p)\n", + txidx, all_mirror_cnt, txinfo[txidx]->tx_sts_m, txinfo[txidx]->tx_sts_m); +} +#endif + + +/*------------------------------------------------------------------------- + * get_txid + * return txid of the transaction at the specified index. + *------------------------------------------------------------------------- + */ +TransactionId +get_txid(int txidx) +{ + return txinfo[txidx]->txid; +} + +/*------------------------------------------------------------------------- + * get_tx + * Return transaction entry which has specified transaction id, or NULL + * if there is no such transaction. + *------------------------------------------------------------------------- + */ +prepared_txninfo * +get_tx(TransactionId txid) +{ + int txloop; + + dispmsg(lvl_debug, "BEGIN: get_tx(%d)", txid); + + for (txlo... [truncated message content] |
From: Michael P. <mic...@us...> - 2011-03-29 19:50:21
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 886f9bbe99120dc751a7d9110521a7cd6cc884d9 (commit) from 82c7049c243ba0849d93b6f73e1b4b96a64f4d9c (commit) - Log ----------------------------------------------------------------- commit 886f9bbe99120dc751a7d9110521a7cd6cc884d9 Author: Michael P <mic...@us...> Date: Wed Mar 30 04:36:37 2011 +0900 Fix for bug 3240318: support for lastval Last value was simply not saved in cache after nextval and setval. diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index aceee06..01df64b 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -623,6 +623,8 @@ nextval_internal(Oid relid) elm->last = result; /* last returned number */ elm->cached = result; /* last fetched number */ elm->last_valid = true; + + last_used_seq = elm; } else { @@ -939,6 +941,15 @@ do_setval(Oid relid, int64 next, bool iscalled) /* Update the on-disk data */ seq->last_value = next; /* last fetched number */ seq->is_called = iscalled; + seq->log_cnt = (iscalled) ? 0 : 1; + + if (iscalled) + { + elm->last = next; /* last returned number */ + elm->last_valid = true; + } + + elm->cached = elm->last; } else { ----------------------------------------------------------------------- Summary of changes: src/backend/commands/sequence.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-29 12:03:24
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 82c7049c243ba0849d93b6f73e1b4b96a64f4d9c (commit) from f61d2df4e202e715877b676bbb194552588b43bd (commit) - Log ----------------------------------------------------------------- commit 82c7049c243ba0849d93b6f73e1b4b96a64f4d9c Author: Michael P <mic...@us...> Date: Tue Mar 29 21:01:16 2011 +0900 Fix a cache leak WARNING with system cache This was happening because of commit 76f1d9cde238be026007d00a6af192b7f7ac4ce5 because data cached was not released. diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index ad8c568..3458247 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -22,7 +22,6 @@ #include "utils/lsyscache.h" #ifdef PGXC #include "pgxc/pgxc.h" -#include "parser/parse_type.h" #endif static void printtup_startup(DestReceiver *self, int operation, @@ -201,7 +200,7 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats) if (IS_PGXC_DATANODE && IsConnFromCoord()) { char *typename; - typename = typeTypeName(typeidType(atttypid)); + typename = get_typename(atttypid); pq_sendstring(&buf, typename); } #endif diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 8cac03b..3cd7f40 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -2017,6 +2017,30 @@ getBaseTypeAndTypmod(Oid typid, int32 *typmod) return typid; } +#ifdef PGXC +/* + * Get type name for given type ID + */ +char * +get_typename(Oid typid) +{ + HeapTuple tuple; + Form_pg_type typeForm; + char *result; + + tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid)); + + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for type %u", typid); + + typeForm = (Form_pg_type) GETSTRUCT(tuple); + result = pstrdup(NameStr(typeForm->typname)); + ReleaseSysCache(tuple); + + return result; +} +#endif + /* * get_typavgwidth * diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 4c88b59..7f60371 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -127,6 +127,9 @@ extern void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena); extern Oid get_typmodin(Oid typid); extern Oid getBaseType(Oid typid); extern Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod); +#ifdef PGXC +extern char *get_typename(Oid typid); +#endif extern int32 get_typavgwidth(Oid typid, int32 typmod); extern int32 get_attavgwidth(Oid relid, AttrNumber attnum); extern bool get_attstatsslot(HeapTuple statstuple, ----------------------------------------------------------------------- Summary of changes: src/backend/access/common/printtup.c | 3 +-- src/backend/utils/cache/lsyscache.c | 24 ++++++++++++++++++++++++ src/include/utils/lsyscache.h | 3 +++ 3 files changed, 28 insertions(+), 2 deletions(-) hooks/post-receive -- Postgres-XC |
From: Abbas B. <ga...@us...> - 2011-03-28 17:00:29
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via f61d2df4e202e715877b676bbb194552588b43bd (commit) via 09be104bfe29525f3423b3b07a9f88b943c8845e (commit) from 75b80f6575e6c29dc07d2e8cd803a8c2cb309bde (commit) - Log ----------------------------------------------------------------- commit f61d2df4e202e715877b676bbb194552588b43bd Merge: 09be104 75b80f6 Author: Abbas <abb...@en...> Date: Mon Mar 28 21:58:20 2011 +0500 Merge branch 'merge_postgres_9_0_3' of ssh://postgres-xc.git.sourceforge.net/gitroot/postgres-xc/postgres-xc into merge_postgres_9_0_3 commit 09be104bfe29525f3423b3b07a9f88b943c8845e Author: Abbas <abb...@en...> Date: Mon Mar 28 21:49:14 2011 +0500 This patch fixes the problem in XC that error detail was not being handled. This would fix bug id 3220325 and numeric test case would now pass. diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index 95f23f3..7c9ec5b 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -213,6 +213,7 @@ CreateResponseCombiner(int node_count, CombineType combine_type) combiner->copy_in_count = 0; combiner->copy_out_count = 0; combiner->errorMessage = NULL; + combiner->errorDetail = NULL; combiner->query_Done = false; combiner->currentRow.msg = NULL; combiner->currentRow.msglen = 0; @@ -812,6 +813,11 @@ HandleError(RemoteQueryState *combiner, char *msg_body, size_t len) memcpy(combiner->errorCode, code, 5); } + if (!combiner->errorDetail && detail != NULL) + { + combiner->errorDetail = pstrdup(detail); + } + /* * If data node have sent ErrorResponse it will never send CommandComplete. * Increment the counter to prevent endless waiting for it. @@ -950,6 +956,8 @@ CloseCombiner(RemoteQueryState *combiner) FreeTupleDesc(combiner->tuple_desc); if (combiner->errorMessage) pfree(combiner->errorMessage); + if (combiner->errorDetail) + pfree(combiner->errorDetail); if (combiner->cursor_connections) pfree(combiner->cursor_connections); if (combiner->tapenodes) @@ -994,6 +1002,8 @@ ValidateAndResetCombiner(RemoteQueryState *combiner) list_free_deep(combiner->rowBuffer); if (combiner->errorMessage) pfree(combiner->errorMessage); + if (combiner->errorDetail) + pfree(combiner->errorDetail); if (combiner->tapenodes) pfree(combiner->tapenodes); @@ -1006,6 +1016,7 @@ ValidateAndResetCombiner(RemoteQueryState *combiner) combiner->copy_in_count = 0; combiner->copy_out_count = 0; combiner->errorMessage = NULL; + combiner->errorDetail = NULL; combiner->query_Done = false; combiner->currentRow.msg = NULL; combiner->currentRow.msglen = 0; @@ -3344,9 +3355,14 @@ do_query(RemoteQueryState *node) if (node->errorMessage) { char *code = node->errorCode; - ereport(ERROR, - (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), - errmsg("%s", node->errorMessage))); + if (node->errorDetail != NULL) + ereport(ERROR, + (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), + errmsg("%s", node->errorMessage), errdetail("%s", node->errorDetail) )); + else + ereport(ERROR, + (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), + errmsg("%s", node->errorMessage))); } } @@ -3712,9 +3728,14 @@ handle_results: if (node->errorMessage) { char *code = node->errorCode; - ereport(ERROR, - (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), - errmsg("%s", node->errorMessage))); + if (node->errorDetail != NULL) + ereport(ERROR, + (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), + errmsg("%s", node->errorMessage), errdetail("%s", node->errorDetail) )); + else + ereport(ERROR, + (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), + errmsg("%s", node->errorMessage))); } /* @@ -4311,9 +4332,14 @@ ExecRemoteUtility(RemoteQuery *node) if (remotestate->errorMessage) { char *code = remotestate->errorCode; - ereport(ERROR, - (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), - errmsg("%s", remotestate->errorMessage))); + if (remotestate->errorDetail != NULL) + ereport(ERROR, + (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), + errmsg("%s", remotestate->errorMessage), errdetail("%s", remotestate->errorDetail) )); + else + ereport(ERROR, + (errcode(MAKE_SQLSTATE(code[0], code[1], code[2], code[3], code[4])), + errmsg("%s", remotestate->errorMessage))); } } diff --git a/src/include/pgxc/execRemote.h b/src/include/pgxc/execRemote.h index 2b8b8ce..1113468 100644 --- a/src/include/pgxc/execRemote.h +++ b/src/include/pgxc/execRemote.h @@ -82,6 +82,7 @@ typedef struct RemoteQueryState int copy_out_count; /* count of received CopyOut messages */ char errorCode[5]; /* error code to send back to client */ char *errorMessage; /* error message to send back to client */ + char *errorDetail; /* error detail to send back to client */ bool query_Done; /* query has been sent down to data nodes */ RemoteDataRowData currentRow; /* next data ro to be wrapped into a tuple */ /* TODO use a tuplestore as a rowbuffer */ diff --git a/src/test/regress/expected/numeric_1.out b/src/test/regress/expected/numeric_1.out index 89c19c9..b93d694 100644 --- a/src/test/regress/expected/numeric_1.out +++ b/src/test/regress/expected/numeric_1.out @@ -688,10 +688,12 @@ INSERT INTO fract_only VALUES (1, '0.0'); INSERT INTO fract_only VALUES (2, '0.1'); INSERT INTO fract_only VALUES (3, '1.0'); -- should fail ERROR: numeric field overflow +DETAIL: A field with precision 4, scale 4 must round to an absolute value less than 1. INSERT INTO fract_only VALUES (4, '-0.9999'); INSERT INTO fract_only VALUES (5, '0.99994'); INSERT INTO fract_only VALUES (6, '0.99995'); -- should fail ERROR: numeric field overflow +DETAIL: A field with precision 4, scale 4 must round to an absolute value less than 1. INSERT INTO fract_only VALUES (7, '0.00001'); INSERT INTO fract_only VALUES (8, '0.00017'); SELECT * FROM fract_only ORDER BY id; @@ -1035,16 +1037,16 @@ SELECT '' AS to_char_15, to_char(val, 'FM9999999990999999.099999999999999') FRO SELECT '' AS to_char_16, to_char(val, 'L9999999999999999.099999999999999') FROM num_data ORDER BY val; to_char_16 | to_char ------------+------------------------------------ - | $ -83028485.000000000000000 + | -83028485.000000000000000 | -34338492.215397047000000 - | $ -24926804.045047420000000 - | $ .000000000000000 - | $ .000000000000000 + | -24926804.045047420000000 + | .000000000000000 + | .000000000000000 | 4.310000000000000 | 16397.038491000000000 | 74881.000000000000000 - | $ 93901.577630260000000 - | $ 7799461.411900000000000 + | 93901.577630260000000 + | 7799461.411900000000000 (10 rows) SELECT '' AS to_char_17, to_char(val, 'FM9999999999999999.99999999999999') FROM num_data ORDER BY val; @@ -1137,6 +1139,21 @@ SELECT '' AS to_char_22, to_char(val, 'FM9999999999999999.999999999999999') FROM | 7799461.4119 (10 rows) +SELECT '' AS to_char_23, to_char(val, '9.999EEEE') FROM num_data ORDER BY val; + to_char_23 | to_char +------------+------------ + | -8.303e+07 + | -3.434e+07 + | -2.493e+07 + | 0.000e+00 + | 0.000e+00 + | 4.310e+00 + | 1.640e+04 + | 7.488e+04 + | 9.390e+04 + | 7.799e+06 +(10 rows) + -- TO_NUMBER() -- SELECT '' AS to_number_1, to_number('-34,338,492', '99G999G999'); diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql index 83ee939..1ab688c 100644 --- a/src/test/regress/sql/numeric.sql +++ b/src/test/regress/sql/numeric.sql @@ -762,6 +762,7 @@ SELECT '' AS to_char_19, to_char(val, 'FMS 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 SELECT '' AS to_char_20, to_char(val, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM num_data ORDER BY val; SELECT '' AS to_char_21, to_char(val, '999999SG9999999999') FROM num_data ORDER BY val; SELECT '' AS to_char_22, to_char(val, 'FM9999999999999999.999999999999999') FROM num_data ORDER BY val; +SELECT '' AS to_char_23, to_char(val, '9.999EEEE') FROM num_data ORDER BY val; -- TO_NUMBER() -- ----------------------------------------------------------------------- Summary of changes: src/backend/pgxc/pool/execRemote.c | 44 ++++++++++++++++++++++++------ src/include/pgxc/execRemote.h | 1 + src/test/regress/expected/numeric_1.out | 29 ++++++++++++++++---- src/test/regress/sql/numeric.sql | 1 + 4 files changed, 60 insertions(+), 15 deletions(-) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-28 16:41:26
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 75b80f6575e6c29dc07d2e8cd803a8c2cb309bde (commit) from 6654fe0c6fac62e0351b3a409d26861789e9906b (commit) - Log ----------------------------------------------------------------- commit 75b80f6575e6c29dc07d2e8cd803a8c2cb309bde Author: Michael P <mic...@us...> Date: Tue Mar 29 00:41:24 2011 +0900 Fix for VIEW and SEQUENCE Views were only created on local Coordinator but they need to be created on all Coordinators. DROP VIEW was made on all the nodes, but now it is made only on Coordinator. ALTER SEQUENCE/VIEW ... SET SCHEMA ... ALTER SEQUENCE/VIEW ... RENAME TO ... are also correctly fixed. There was an issue with sequence renaming: CREATE SEQUENCE foo; ALTER SEQUENCE foo RENAME TO foobar; CREATE SEQUENCE foo; -- ERROR Error was caused by sequence with former name which was not correctly removed on GTM. diff --git a/src/backend/access/transam/gtm.c b/src/backend/access/transam/gtm.c index a9bf1d6..e9f0229 100644 --- a/src/backend/access/transam/gtm.c +++ b/src/backend/access/transam/gtm.c @@ -422,7 +422,7 @@ RenameSequenceGTM(char *seqname, const char *newseqname) seqkey.gsk_keylen = strlen(seqname); seqkey.gsk_key = seqname; newseqkey.gsk_keylen = strlen(newseqname); - newseqkey.gsk_key = (char *)newseqname; + newseqkey.gsk_key = (char *) newseqname; return conn ? rename_sequence(conn, &seqkey, &newseqkey) : -1; } diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 09ae5c3..4496bcd 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -33,6 +33,7 @@ #ifdef PGXC #include "pgxc/pgxc.h" +#include "pgxc/planner.h" #endif static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId); @@ -131,7 +132,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString) * Add a RemoteQuery node for a query at top level on a remote Coordinator */ if (is_top_level) - parsetree_list = AddRemoteQueryNode(parsetree_list, queryString); + parsetree_list = AddRemoteQueryNode(parsetree_list, queryString, EXEC_ON_ALL_NODES); #endif /* diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 8a921f5..aceee06 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -1448,7 +1448,7 @@ GetGlobalSeqName(Relation seqrel, const char *new_seqname, const char *new_schem /* Get all the necessary relation names */ dbname = get_database_name(seqrel->rd_node.dbNode); - + if (new_seqname) relname = (char *) new_seqname; else diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 18e9358..67a14c8 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -80,6 +80,7 @@ #ifdef PGXC #include "pgxc/pgxc.h" #include "access/gtm.h" +#include "commands/sequence.h" #endif /* @@ -7962,6 +7963,26 @@ AlterTableNamespace(RangeVar *relation, const char *newschema, heap_close(classRel, RowExclusiveLock); +#ifdef PGXC + /* Rename also sequence on GTM for a sequence */ + if (IS_PGXC_COORDINATOR && + !IsConnFromCoord() && + rel->rd_rel->relkind == RELKIND_SEQUENCE) + { + char *seqname = GetGlobalSeqName(rel, NULL, NULL); + char *newseqname = GetGlobalSeqName(rel, NULL, newschema); + + /* 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"))); + + pfree(seqname); + pfree(newseqname); + } +#endif + /* close rel, but keep lock until commit */ relation_close(rel, NoLock); } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 21b5cfd..9b48756 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -2633,30 +2633,4 @@ checkLocalFKConstraints(CreateStmtContext *cxt) } } } - -/* - * AddRemoteQueryNode - * - * Add a Remote Query node to launch on Datanodes. - * This can only be done for a query a Top Level to avoid - * duplicated queries on Datanodes. - */ -List * -AddRemoteQueryNode(List *stmts, const char *queryString) -{ - List *result = stmts; - - /* Only a remote Coordinator is allowed to send a query to backend nodes */ - if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) - { - RemoteQuery *step = makeNode(RemoteQuery); - step->combine_type = COMBINE_TYPE_SAME; - step->sql_statement = queryString; - /* This query is a DDL, Launch it on both Datanodes and Coordinators. */ - step->exec_type = EXEC_ON_ALL_NODES; - result = lappend(result, step); - } - - return result; -} #endif diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index 90031fa..45c453a 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -33,6 +33,7 @@ #include "parser/parse_agg.h" #include "parser/parse_coerce.h" #include "pgxc/execRemote.h" +#include "pgxc/pgxc.h" #include "pgxc/locator.h" #include "pgxc/planner.h" #include "tcop/pquery.h" @@ -3353,3 +3354,27 @@ GetHashExecNodes(RelationLocInfo *rel_loc_info, ExecNodes **exec_nodes, const Ex } +/* + * AddRemoteQueryNode + * + * Add a Remote Query node to launch on Datanodes. + * This can only be done for a query a Top Level to avoid + * duplicated queries on Datanodes. + */ +List * +AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType remoteExecType) +{ + List *result = stmts; + + /* Only a remote Coordinator is allowed to send a query to backend nodes */ + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + { + RemoteQuery *step = makeNode(RemoteQuery); + step->combine_type = COMBINE_TYPE_SAME; + step->sql_statement = queryString; + step->exec_type = remoteExecType; + result = lappend(result, step); + } + + return result; +} diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index d06fdb2..284a52c 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -615,7 +615,7 @@ standard_ProcessUtility(Node *parsetree, * Add a RemoteQuery node for a query at top level on a remote Coordinator */ if (isTopLevel) - stmts = AddRemoteQueryNode(stmts, queryString); + stmts = AddRemoteQueryNode(stmts, queryString, EXEC_ON_ALL_NODES); #endif /* ... and do it */ @@ -773,14 +773,14 @@ standard_ProcessUtility(Node *parsetree, } #ifdef PGXC /* - * PGXCTODO - * We may need to check details of the object being dropped and + * We need to check details of the object being dropped and * run command on correct nodes */ - if (IS_PGXC_COORDINATOR) + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) { - /* Sequence exists only on Coordinators */ - if (stmt->removeType == OBJECT_SEQUENCE) + /* Sequence and views exists only on Coordinators */ + if (stmt->removeType == OBJECT_SEQUENCE || + stmt->removeType == OBJECT_VIEW) ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS); else ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); @@ -854,7 +854,8 @@ standard_ProcessUtility(Node *parsetree, RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES; RenameStmt *stmt = (RenameStmt *) parsetree; - if (stmt->renameType == OBJECT_SEQUENCE) + if (stmt->renameType == OBJECT_SEQUENCE || + stmt->renameType == OBJECT_VIEW) remoteExecType = EXEC_ON_COORDS; else if (stmt->renameType == OBJECT_TABLE) { @@ -872,8 +873,23 @@ standard_ProcessUtility(Node *parsetree, case T_AlterObjectSchemaStmt: #ifdef PGXC - if (IS_PGXC_COORDINATOR) - ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_ALL_NODES); + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + { + RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES; + AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree; + + if (stmt->objectType == OBJECT_SEQUENCE || + stmt->objectType == OBJECT_VIEW) + remoteExecType = EXEC_ON_COORDS; + else if (stmt->objectType == OBJECT_TABLE) + { + Oid relid = RangeVarGetRelid(stmt->relation, false); + + if (get_rel_relkind(relid) == RELKIND_SEQUENCE) + remoteExecType = EXEC_ON_COORDS; + } + ExecUtilityStmtOnNodes(queryString, NULL, false, remoteExecType); + } #endif ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree); break; @@ -895,7 +911,23 @@ standard_ProcessUtility(Node *parsetree, * Add a RemoteQuery node for a query at top level on a remote Coordinator */ if (isTopLevel) - stmts = AddRemoteQueryNode(stmts, queryString); + { + RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES; + AlterTableStmt *stmt = (AlterTableStmt *) parsetree; + + if (stmt->relkind == OBJECT_VIEW || + stmt->relkind == OBJECT_SEQUENCE) + remoteExecType = EXEC_ON_COORDS; + else if (stmt->relkind == OBJECT_TABLE) + { + Oid relid = RangeVarGetRelid(stmt->relation, false); + + if (get_rel_relkind(relid) == RELKIND_SEQUENCE) + remoteExecType = EXEC_ON_COORDS; + } + + stmts = AddRemoteQueryNode(stmts, queryString, remoteExecType); + } #endif /* ... and do it */ @@ -1057,6 +1089,10 @@ standard_ProcessUtility(Node *parsetree, case T_ViewStmt: /* CREATE VIEW */ DefineView((ViewStmt *) parsetree, queryString); +#ifdef PGXC + if (IS_PGXC_COORDINATOR) + ExecUtilityStmtOnNodes(queryString, NULL, false, EXEC_ON_COORDS); +#endif break; case T_CreateFunctionStmt: /* CREATE FUNCTION */ diff --git a/src/gtm/Makefile.global b/src/gtm/Makefile.global index bfc052f..684690b 100644 --- a/src/gtm/Makefile.global +++ b/src/gtm/Makefile.global @@ -29,7 +29,7 @@ enable_shared = yes # Compilers CPP = gcc -E -CPPFLAGS = -D_GNU_SOURCE +CPPFLAGS = -g -D_GNU_SOURCE override CPPFLAGS := -I$(top_srcdir)/include $(CPPFLAGS) diff --git a/src/gtm/main/gtm_seq.c b/src/gtm/main/gtm_seq.c index 8c15fe9..f6c4a21 100644 --- a/src/gtm/main/gtm_seq.c +++ b/src/gtm/main/gtm_seq.c @@ -636,6 +636,8 @@ GTM_SeqRename(GTM_SequenceKey seqkey, GTM_SequenceKey newseqkey) /* Release first the structure as it has been taken previously */ seq_release_seqinfo(seqinfo); + /* Close sequence properly, full name is here */ + seqkey->gsk_type = GTM_SEQ_FULL_NAME; /* Then close properly the old sequence */ GTM_SeqClose(seqkey); return errcode; diff --git a/src/include/parser/parse_utilcmd.h b/src/include/parser/parse_utilcmd.h index 256c583..3f9b8f9 100644 --- a/src/include/parser/parse_utilcmd.h +++ b/src/include/parser/parse_utilcmd.h @@ -27,7 +27,6 @@ extern void transformRuleStmt(RuleStmt *stmt, const char *queryString, extern List *transformCreateSchemaStmt(CreateSchemaStmt *stmt); #ifdef PGXC extern bool CheckLocalIndexColumn (char loctype, char *partcolname, char *indexcolname); -extern List *AddRemoteQueryNode(List *stmts, const char *queryString); #endif #endif /* PARSE_UTILCMD_H */ diff --git a/src/include/pgxc/planner.h b/src/include/pgxc/planner.h index 4e4cd62..b69f940 100644 --- a/src/include/pgxc/planner.h +++ b/src/include/pgxc/planner.h @@ -210,4 +210,6 @@ extern bool is_immutable_func(Oid funcid); extern bool IsJoinReducible(RemoteQuery *innernode, RemoteQuery *outernode, List *rtable_list, JoinPath *join_path, JoinReduceInfo *join_info); +extern List *AddRemoteQueryNode(List *stmts, const char *queryString, RemoteQueryExecType remoteExecType); + #endif /* PGXCPLANNER_H */ diff --git a/src/test/regress/expected/privileges_1.out b/src/test/regress/expected/privileges_1.out index 90043e4..94b9267 100644 --- a/src/test/regress/expected/privileges_1.out +++ b/src/test/regress/expected/privileges_1.out @@ -1226,29 +1226,16 @@ ERROR: function testfunc2(integer) does not exist DROP FUNCTION testfunc4(boolean); ERROR: function testfunc4(boolean) does not exist DROP VIEW atestv1; -ERROR: view "atestv1" does not exist DROP VIEW atestv2; -ERROR: view "atestv2" does not exist -- this should cascade to drop atestv4 DROP VIEW atestv3 CASCADE; NOTICE: drop cascades to view atestv4 -ERROR: view "atestv3" does not exist -- this should complain "does not exist" DROP VIEW atestv4; ERROR: view "atestv4" does not exist DROP TABLE atest1; -ERROR: cannot drop table atest1 because other objects depend on it -DETAIL: view atestv1 depends on table atest1 -HINT: Use DROP ... CASCADE to drop the dependent objects too. DROP TABLE atest2; -ERROR: cannot drop table atest2 because other objects depend on it -DETAIL: view atestv2 depends on table atest2 -HINT: Use DROP ... CASCADE to drop the dependent objects too. DROP TABLE atest3; -ERROR: cannot drop table atest3 because other objects depend on it -DETAIL: view atestv3 depends on table atest3 -view atestv4 depends on view atestv3 -HINT: Use DROP ... CASCADE to drop the dependent objects too. DROP TABLE atest4; DROP TABLE atest5; DROP TABLE atest6; @@ -1268,43 +1255,13 @@ SELECT lo_unlink(oid) FROM pg_largeobject_metadata; DROP GROUP regressgroup1; DROP GROUP regressgroup2; -ERROR: role "regressgroup2" cannot be dropped because some objects depend on it -DETAIL: privileges for table atest3 -- these are needed to clean up permissions REVOKE USAGE ON LANGUAGE sql FROM regressuser1; DROP OWNED BY regressuser1; -ERROR: cannot drop desired object(s) because other objects depend on them -DETAIL: view atestv1 depends on table atest1 -view atestv2 depends on table atest2 -HINT: Use DROP ... CASCADE to drop the dependent objects too. DROP USER regressuser1; -ERROR: role "regressuser1" cannot be dropped because some objects depend on it -DETAIL: owner of default privileges on new functions belonging to role regressuser1 -owner of table atest2 -owner of table atest1 DROP USER regressuser2; -ERROR: role "regressuser2" cannot be dropped because some objects depend on it -DETAIL: privileges for view atestv4 -privileges for view atestv2 -privileges for table atest2 -privileges for table atest1 DROP USER regressuser3; -ERROR: role "regressuser3" cannot be dropped because some objects depend on it -DETAIL: owner of view atestv3 -owner of view atestv2 -owner of view atestv1 -owner of table atest3 -privileges for table atest2 -privileges for table atest1 DROP USER regressuser4; -ERROR: role "regressuser4" cannot be dropped because some objects depend on it -DETAIL: owner of view atestv4 -privileges for view atestv3 -privileges for view atestv1 -privileges for table atest2 -privileges for table atest1 DROP USER regressuser5; -ERROR: role "regressuser5" cannot be dropped because some objects depend on it -DETAIL: privileges for table atest2 DROP USER regressuser6; ERROR: role "regressuser6" does not exist ----------------------------------------------------------------------- Summary of changes: src/backend/access/transam/gtm.c | 2 +- src/backend/commands/schemacmds.c | 3 +- src/backend/commands/sequence.c | 2 +- src/backend/commands/tablecmds.c | 21 ++++++++++ src/backend/parser/parse_utilcmd.c | 26 ------------- src/backend/pgxc/plan/planner.c | 25 ++++++++++++ src/backend/tcop/utility.c | 56 +++++++++++++++++++++++----- src/gtm/Makefile.global | 2 +- src/gtm/main/gtm_seq.c | 2 + src/include/parser/parse_utilcmd.h | 1 - src/include/pgxc/planner.h | 2 + src/test/regress/expected/privileges_1.out | 43 --------------------- 12 files changed, 101 insertions(+), 84 deletions(-) hooks/post-receive -- Postgres-XC |
From: Abbas B. <ga...@us...> - 2011-03-28 15:00:53
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 6654fe0c6fac62e0351b3a409d26861789e9906b (commit) from 4f1d506fd83393fbbe98797fa49e862b5b17f19e (commit) - Log ----------------------------------------------------------------- commit 6654fe0c6fac62e0351b3a409d26861789e9906b Author: Abbas <abb...@en...> Date: Mon Mar 28 19:49:56 2011 +0500 This patch fixes a test case in strings.sql SELECT CAST(f1 as text) AS "f2" FROM CHAR_TBL ORDER BY f1 was reporting ERROR: ORDER BY "f1" is ambiguous The problem was in the function reconstruct_step_query. The function was reconstructing the query to look like SELECT (f1)::text, f1 FROM CHAR_TBL ORDER BY f1 and when this query was being sent to the data node, it was complaining. The solution adopted in this patch is to add column alias (if any) while reconstructing the query. Some cosmetic changes were also required for the strings test to pass. diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index e4d13cb..90031fa 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -2257,6 +2257,9 @@ reconstruct_step_query(List *rtable, bool has_order_by, List *extra_sort, appendStringInfo(buf, ", "); appendStringInfoString(buf, exprstr); + + if (tle->resname != NULL) + appendStringInfo(buf, " AS %s", quote_identifier(tle->resname)); } /* diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out index 140c677..4773327 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -996,7 +996,7 @@ SELECT 'Hawkeye' NOT ILIKE 'h%' AS "false"; (1 row) -- --- test %/_ combination cases, cf bug #4821 +-- test %/_ combination cases, cf bugs #4821 and #5478 -- SELECT 'foo' LIKE '_%' as t, 'f' LIKE '_%' as t, '' LIKE '_%' as f; t | t | f diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings_1.out similarity index 99% copy from src/test/regress/expected/strings.out copy to src/test/regress/expected/strings_1.out index 140c677..2bbdf50 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings_1.out @@ -996,7 +996,7 @@ SELECT 'Hawkeye' NOT ILIKE 'h%' AS "false"; (1 row) -- --- test %/_ combination cases, cf bug #4821 +-- test %/_ combination cases, cf bugs #4821 and #5478 -- SELECT 'foo' LIKE '_%' as t, 'f' LIKE '_%' as t, '' LIKE '_%' as f; t | t | f @@ -1128,12 +1128,12 @@ insert into toasttest values(decode(repeat('1234567890',10000),'escape')); -- If the starting position is zero or less, then return from the start of the string -- adjusting the length to be consistent with the "negative start" per SQL92. SELECT substr(f1, -1, 5) from toasttest; - substr --------- - 123 - 123 - 123 - 123 + substr +---------- + \x313233 + \x313233 + \x313233 + \x313233 (4 rows) -- If the length is less than zero, an ERROR is thrown. @@ -1142,23 +1142,23 @@ ERROR: negative substring length not allowed -- If no third argument (length) is provided, the length to the end of the -- string is assumed. SELECT substr(f1, 99995) from toasttest; - substr --------- - 567890 - 567890 - 567890 - 567890 + substr +---------------- + \x353637383930 + \x353637383930 + \x353637383930 + \x353637383930 (4 rows) -- If start plus length is > string length, the result is truncated to -- string length SELECT substr(f1, 99995, 10) from toasttest; - substr --------- - 567890 - 567890 - 567890 - 567890 + substr +---------------- + \x353637383930 + \x353637383930 + \x353637383930 + \x353637383930 (4 rows) DROP TABLE toasttest; ----------------------------------------------------------------------- Summary of changes: src/backend/pgxc/plan/planner.c | 3 ++ src/test/regress/expected/strings.out | 2 +- .../expected/{strings.out => strings_1.out} | 38 ++++++++++---------- 3 files changed, 23 insertions(+), 20 deletions(-) copy src/test/regress/expected/{strings.out => strings_1.out} (99%) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-25 17:11:16
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 4f1d506fd83393fbbe98797fa49e862b5b17f19e (commit) from 796bf6e4b113d356b7d725daa71d62835faf9c68 (commit) - Log ----------------------------------------------------------------- commit 4f1d506fd83393fbbe98797fa49e862b5b17f19e Author: Michael P <mic...@us...> Date: Sat Mar 26 02:09:57 2011 +0900 Fix for regression test privileges Postgres-XC does not support yet TEMP tables and non-immutable functions, so this output is correct. diff --git a/src/test/regress/expected/privileges_1.out b/src/test/regress/expected/privileges_1.out new file mode 100644 index 0000000..90043e4 --- /dev/null +++ b/src/test/regress/expected/privileges_1.out @@ -0,0 +1,1310 @@ +-- +-- Test access privileges +-- +-- Clean up in case a prior regression run failed +-- Suppress NOTICE messages when users/groups don't exist +SET client_min_messages TO 'warning'; +DROP ROLE IF EXISTS regressgroup1; +DROP ROLE IF EXISTS regressgroup2; +DROP ROLE IF EXISTS regressuser1; +DROP ROLE IF EXISTS regressuser2; +DROP ROLE IF EXISTS regressuser3; +DROP ROLE IF EXISTS regressuser4; +DROP ROLE IF EXISTS regressuser5; +DROP ROLE IF EXISTS regressuser6; +SELECT lo_unlink(oid) FROM pg_largeobject_metadata; + lo_unlink +----------- +(0 rows) + +RESET client_min_messages; +-- test proper begins here +CREATE USER regressuser1; +CREATE USER regressuser2; +CREATE USER regressuser3; +CREATE USER regressuser4; +CREATE USER regressuser5; +CREATE USER regressuser5; -- duplicate +ERROR: role "regressuser5" already exists +CREATE GROUP regressgroup1; +CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2; +ALTER GROUP regressgroup1 ADD USER regressuser4; +ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate +NOTICE: role "regressuser2" is already a member of role "regressgroup2" +ALTER GROUP regressgroup2 DROP USER regressuser2; +ALTER GROUP regressgroup2 ADD USER regressuser4; +-- test owner privileges +SET SESSION AUTHORIZATION regressuser1; +SELECT session_user, current_user; + session_user | current_user +--------------+-------------- + regressuser1 | regressuser1 +(1 row) + +CREATE TABLE atest1 ( a int, b text ); +SELECT * FROM atest1; + a | b +---+--- +(0 rows) + +INSERT INTO atest1 VALUES (1, 'one'); +DELETE FROM atest1; +UPDATE atest1 SET a = 1 WHERE b = 'blech'; +ERROR: Partition column can't be updated in current version +TRUNCATE atest1; +BEGIN; +LOCK atest1 IN ACCESS EXCLUSIVE MODE; +COMMIT; +REVOKE ALL ON atest1 FROM PUBLIC; +SELECT * FROM atest1; + a | b +---+--- +(0 rows) + +GRANT ALL ON atest1 TO regressuser2; +GRANT SELECT ON atest1 TO regressuser3, regressuser4; +SELECT * FROM atest1; + a | b +---+--- +(0 rows) + +CREATE TABLE atest2 (col1 varchar(10), col2 boolean); +GRANT SELECT ON atest2 TO regressuser2; +GRANT UPDATE ON atest2 TO regressuser3; +GRANT INSERT ON atest2 TO regressuser4; +GRANT TRUNCATE ON atest2 TO regressuser5; +SET SESSION AUTHORIZATION regressuser2; +SELECT session_user, current_user; + session_user | current_user +--------------+-------------- + regressuser2 | regressuser2 +(1 row) + +-- try various combinations of queries on atest1 and atest2 +SELECT * FROM atest1; -- ok + a | b +---+--- +(0 rows) + +SELECT * FROM atest2; -- ok + col1 | col2 +------+------ +(0 rows) + +INSERT INTO atest1 VALUES (2, 'two'); -- ok +INSERT INTO atest2 VALUES ('foo', true); -- fail +ERROR: permission denied for relation atest2 +INSERT INTO atest1 SELECT 1, b FROM atest1; -- ok +UPDATE atest1 SET a = 1 WHERE a = 2; -- ok +ERROR: Partition column can't be updated in current version +UPDATE atest2 SET col2 = NOT col2; -- fail +ERROR: permission denied for relation atest2 +SELECT * FROM atest1 FOR UPDATE; -- ok + a | b +---+----- + 2 | two +(1 row) + +SELECT * FROM atest2 FOR UPDATE; -- fail +ERROR: permission denied for relation atest2 +DELETE FROM atest2; -- fail +ERROR: permission denied for relation atest2 +TRUNCATE atest2; -- fail +ERROR: permission denied for relation atest2 +BEGIN; +LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail +ERROR: permission denied for relation atest2 +COMMIT; +COPY atest2 FROM stdin; -- fail +ERROR: permission denied for relation atest2 +GRANT ALL ON atest1 TO PUBLIC; -- fail +WARNING: no privileges were granted for "atest1" +-- checks in subquery, both ok +SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); + a | b +---+--- +(0 rows) + +SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) ); + col1 | col2 +------+------ +(0 rows) + +SET SESSION AUTHORIZATION regressuser3; +SELECT session_user, current_user; + session_user | current_user +--------------+-------------- + regressuser3 | regressuser3 +(1 row) + +SELECT * FROM atest1; -- ok + a | b +---+----- + 2 | two +(1 row) + +SELECT * FROM atest2; -- fail +ERROR: permission denied for relation atest2 +INSERT INTO atest1 VALUES (2, 'two'); -- fail +ERROR: permission denied for relation atest1 +INSERT INTO atest2 VALUES ('foo', true); -- fail +ERROR: permission denied for relation atest2 +INSERT INTO atest1 SELECT 1, b FROM atest1; -- fail +ERROR: permission denied for relation atest1 +UPDATE atest1 SET a = 1 WHERE a = 2; -- fail +ERROR: Partition column can't be updated in current version +UPDATE atest2 SET col2 = NULL; -- ok +UPDATE atest2 SET col2 = NOT col2; -- fails; requires SELECT on atest2 +ERROR: permission denied for relation atest2 +UPDATE atest2 SET col2 = true FROM atest1 WHERE atest1.a = 5; -- ok +SELECT * FROM atest1 FOR UPDATE; -- fail +ERROR: permission denied for relation atest1 +SELECT * FROM atest2 FOR UPDATE; -- fail +ERROR: permission denied for relation atest2 +DELETE FROM atest2; -- fail +ERROR: permission denied for relation atest2 +TRUNCATE atest2; -- fail +ERROR: permission denied for relation atest2 +BEGIN; +LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok +COMMIT; +COPY atest2 FROM stdin; -- fail +ERROR: permission denied for relation atest2 +-- checks in subquery, both fail +SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); +ERROR: permission denied for relation atest2 +SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) ); +ERROR: permission denied for relation atest2 +SET SESSION AUTHORIZATION regressuser4; +COPY atest2 FROM stdin; -- ok +SELECT * FROM atest1; -- ok + a | b +---+----- + 2 | two +(1 row) + +-- groups +SET SESSION AUTHORIZATION regressuser3; +CREATE TABLE atest3 (one int, two int, three int); +GRANT DELETE ON atest3 TO GROUP regressgroup2; +SET SESSION AUTHORIZATION regressuser1; +SELECT * FROM atest3; -- fail +ERROR: permission denied for relation atest3 +DELETE FROM atest3; -- ok +-- views +SET SESSION AUTHORIZATION regressuser3; +CREATE VIEW atestv1 AS SELECT * FROM atest1; -- ok +/* The next *should* fail, but it's not implemented that way yet. */ +CREATE VIEW atestv2 AS SELECT * FROM atest2; +CREATE VIEW atestv3 AS SELECT * FROM atest3; -- ok +SELECT * FROM atestv1; -- ok + a | b +---+----- + 2 | two +(1 row) + +SELECT * FROM atestv2; -- fail +ERROR: permission denied for relation atest2 +GRANT SELECT ON atestv1, atestv3 TO regressuser4; +GRANT SELECT ON atestv2 TO regressuser2; +SET SESSION AUTHORIZATION regressuser4; +SELECT * FROM atestv1; -- ok + a | b +---+----- + 2 | two +(1 row) + +SELECT * FROM atestv2; -- fail +ERROR: permission denied for relation atestv2 +SELECT * FROM atestv3; -- ok + one | two | three +-----+-----+------- +(0 rows) + +CREATE VIEW atestv4 AS SELECT * FROM atestv3; -- nested view +SELECT * FROM atestv4; -- ok + one | two | three +-----+-----+------- +(0 rows) + +GRANT SELECT ON atestv4 TO regressuser2; +SET SESSION AUTHORIZATION regressuser2; +-- Two complex cases: +SELECT * FROM atestv3; -- fail +ERROR: permission denied for relation atestv3 +SELECT * FROM atestv4; -- ok (even though regressuser2 cannot access underlying atestv3) + one | two | three +-----+-----+------- +(0 rows) + +SELECT * FROM atest2; -- ok + col1 | col2 +------+------ + bar | t +(1 row) + +SELECT * FROM atestv2; -- fail (even though regressuser2 can access underlying atest2) +ERROR: permission denied for relation atest2 +-- Test column level permissions +SET SESSION AUTHORIZATION regressuser1; +CREATE TABLE atest5 (one int, two int, three int); +CREATE TABLE atest6 (one int, two int, blue int); +GRANT SELECT (one), INSERT (two), UPDATE (three) ON atest5 TO regressuser4; +GRANT ALL (one) ON atest5 TO regressuser3; +INSERT INTO atest5 VALUES (1,2,3); +SET SESSION AUTHORIZATION regressuser4; +SELECT * FROM atest5; -- fail +ERROR: permission denied for relation atest5 +SELECT one FROM atest5; -- ok + one +----- + 1 +(1 row) + +COPY atest5 (one) TO stdout; -- ok +1 +SELECT two FROM atest5; -- fail +ERROR: permission denied for relation atest5 +COPY atest5 (two) TO stdout; -- fail +ERROR: permission denied for relation atest5 +SELECT atest5 FROM atest5; -- fail +ERROR: permission denied for relation atest5 +COPY atest5 (one,two) TO stdout; -- fail +ERROR: permission denied for relation atest5 +SELECT 1 FROM atest5; -- ok + ?column? +---------- + 1 +(1 row) + +SELECT 1 FROM atest5 a JOIN atest5 b USING (one); -- ok + ?column? +---------- + 1 +(1 row) + +SELECT 1 FROM atest5 a JOIN atest5 b USING (two); -- fail +ERROR: permission denied for relation atest5 +SELECT 1 FROM atest5 a NATURAL JOIN atest5 b; -- fail +ERROR: permission denied for relation atest5 +SELECT (j.*) IS NULL FROM (atest5 a JOIN atest5 b USING (one)) j; -- fail +ERROR: permission denied for relation atest5 +SELECT 1 FROM atest5 WHERE two = 2; -- fail +ERROR: permission denied for relation atest5 +SELECT * FROM atest1, atest5; -- fail +ERROR: permission denied for relation atest5 +SELECT atest1.* FROM atest1, atest5; -- ok + a | b +---+----- + 2 | two +(1 row) + +SELECT atest1.*,atest5.one FROM atest1, atest5; -- ok + a | b | one +---+-----+----- + 2 | two | 1 +(1 row) + +SELECT atest1.*,atest5.one FROM atest1 JOIN atest5 ON (atest1.a = atest5.two); -- fail +ERROR: permission denied for relation atest5 +SELECT atest1.*,atest5.one FROM atest1 JOIN atest5 ON (atest1.a = atest5.one); -- ok + a | b | one +---+---+----- +(0 rows) + +SELECT one, two FROM atest5; -- fail +ERROR: permission denied for relation atest5 +SET SESSION AUTHORIZATION regressuser1; +GRANT SELECT (one,two) ON atest6 TO regressuser4; +SET SESSION AUTHORIZATION regressuser4; +SELECT one, two FROM atest5 NATURAL JOIN atest6; -- fail still +ERROR: permission denied for relation atest5 +SET SESSION AUTHORIZATION regressuser1; +GRANT SELECT (two) ON atest5 TO regressuser4; +SET SESSION AUTHORIZATION regressuser4; +SELECT one, two FROM atest5 NATURAL JOIN atest6; -- ok now + one | two +-----+----- +(0 rows) + +-- test column-level privileges for INSERT and UPDATE +INSERT INTO atest5 (two) VALUES (3); -- ok +COPY atest5 FROM stdin; -- fail +ERROR: permission denied for relation atest5 +COPY atest5 (two) FROM stdin; -- ok +INSERT INTO atest5 (three) VALUES (4); -- fail +ERROR: permission denied for relation atest5 +INSERT INTO atest5 VALUES (5,5,5); -- fail +ERROR: permission denied for relation atest5 +UPDATE atest5 SET three = 10; -- ok +UPDATE atest5 SET one = 8; -- fail +ERROR: Partition column can't be updated in current version +UPDATE atest5 SET three = 5, one = 2; -- fail +ERROR: Partition column can't be updated in current version +SET SESSION AUTHORIZATION regressuser1; +REVOKE ALL (one) ON atest5 FROM regressuser4; +GRANT SELECT (one,two,blue) ON atest6 TO regressuser4; +SET SESSION AUTHORIZATION regressuser4; +SELECT one FROM atest5; -- fail +ERROR: permission denied for relation atest5 +UPDATE atest5 SET one = 1; -- fail +ERROR: Partition column can't be updated in current version +SELECT atest6 FROM atest6; -- ok + atest6 +-------- +(0 rows) + +COPY atest6 TO stdout; -- ok +-- test column-level privileges when involved with DELETE +SET SESSION AUTHORIZATION regressuser1; +ALTER TABLE atest6 ADD COLUMN three integer; +GRANT DELETE ON atest5 TO regressuser3; +GRANT SELECT (two) ON atest5 TO regressuser3; +REVOKE ALL (one) ON atest5 FROM regressuser3; +GRANT SELECT (one) ON atest5 TO regressuser4; +SET SESSION AUTHORIZATION regressuser4; +SELECT atest6 FROM atest6; -- fail +ERROR: permission denied for relation atest6 +SELECT one FROM atest5 NATURAL JOIN atest6; -- fail +ERROR: permission denied for relation atest5 +SET SESSION AUTHORIZATION regressuser1; +ALTER TABLE atest6 DROP COLUMN three; +SET SESSION AUTHORIZATION regressuser4; +SELECT atest6 FROM atest6; -- ok + atest6 +-------- +(0 rows) + +SELECT one FROM atest5 NATURAL JOIN atest6; -- ok + one +----- +(0 rows) + +SET SESSION AUTHORIZATION regressuser1; +ALTER TABLE atest6 DROP COLUMN two; +REVOKE SELECT (one,blue) ON atest6 FROM regressuser4; +SET SESSION AUTHORIZATION regressuser4; +SELECT * FROM atest6; -- fail +ERROR: permission denied for relation atest6 +SELECT 1 FROM atest6; -- fail +ERROR: permission denied for relation atest6 +SET SESSION AUTHORIZATION regressuser3; +DELETE FROM atest5 WHERE one = 1; -- fail +ERROR: permission denied for relation atest5 +DELETE FROM atest5 WHERE two = 2; -- ok +-- check inheritance cases +SET SESSION AUTHORIZATION regressuser1; +CREATE TABLE atestp1 (f1 int, f2 int) WITH OIDS; +CREATE TABLE atestp2 (fx int, fy int) WITH OIDS; +CREATE TABLE atestc (fz int) INHERITS (atestp1, atestp2); +ERROR: Cannot currently distribute a table with more than one parent. +GRANT SELECT(fx,fy,oid) ON atestp2 TO regressuser2; +GRANT SELECT(fx) ON atestc TO regressuser2; +ERROR: relation "atestc" does not exist +SET SESSION AUTHORIZATION regressuser2; +SELECT fx FROM atestp2; -- ok + fx +---- +(0 rows) + +SELECT fy FROM atestp2; -- ok + fy +---- +(0 rows) + +SELECT atestp2 FROM atestp2; -- ok + atestp2 +--------- +(0 rows) + +SELECT oid FROM atestp2; -- ok + oid +----- +(0 rows) + +SELECT fy FROM atestc; -- fail +ERROR: relation "atestc" does not exist +LINE 1: SELECT fy FROM atestc; + ^ +SET SESSION AUTHORIZATION regressuser1; +GRANT SELECT(fy,oid) ON atestc TO regressuser2; +ERROR: relation "atestc" does not exist +SET SESSION AUTHORIZATION regressuser2; +SELECT fx FROM atestp2; -- still ok + fx +---- +(0 rows) + +SELECT fy FROM atestp2; -- ok + fy +---- +(0 rows) + +SELECT atestp2 FROM atestp2; -- ok + atestp2 +--------- +(0 rows) + +SELECT oid FROM atestp2; -- ok + oid +----- +(0 rows) + +-- privileges on functions, languages +-- switch to superuser +\c - +REVOKE ALL PRIVILEGES ON LANGUAGE sql FROM PUBLIC; +GRANT USAGE ON LANGUAGE sql TO regressuser1; -- ok +GRANT USAGE ON LANGUAGE c TO PUBLIC; -- fail +ERROR: language "c" is not trusted +HINT: Only superusers can use untrusted languages. +SET SESSION AUTHORIZATION regressuser1; +GRANT USAGE ON LANGUAGE sql TO regressuser2; -- fail +WARNING: no privileges were granted for "sql" +CREATE FUNCTION testfunc1(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql; +ERROR: stable and volatile not yet supported, function volatility has to be immutable +CREATE FUNCTION testfunc2(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql; +ERROR: stable and volatile not yet supported, function volatility has to be immutable +REVOKE ALL ON FUNCTION testfunc1(int), testfunc2(int) FROM PUBLIC; +ERROR: function testfunc1(integer) does not exist +GRANT EXECUTE ON FUNCTION testfunc1(int), testfunc2(int) TO regressuser2; +ERROR: function testfunc1(integer) does not exist +GRANT USAGE ON FUNCTION testfunc1(int) TO regressuser3; -- semantic error +ERROR: function testfunc1(integer) does not exist +GRANT ALL PRIVILEGES ON FUNCTION testfunc1(int) TO regressuser4; +ERROR: function testfunc1(integer) does not exist +GRANT ALL PRIVILEGES ON FUNCTION testfunc_nosuch(int) TO regressuser4; +ERROR: function testfunc_nosuch(integer) does not exist +CREATE FUNCTION testfunc4(boolean) RETURNS text + AS 'select col1 from atest2 where col2 = $1;' + LANGUAGE sql SECURITY DEFINER; +ERROR: stable and volatile not yet supported, function volatility has to be immutable +GRANT EXECUTE ON FUNCTION testfunc4(boolean) TO regressuser3; +ERROR: function testfunc4(boolean) does not exist +SET SESSION AUTHORIZATION regressuser2; +SELECT testfunc1(5), testfunc2(5); -- ok +ERROR: function testfunc1(integer) does not exist +LINE 1: SELECT testfunc1(5), testfunc2(5); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +CREATE FUNCTION testfunc3(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql; -- fail +ERROR: permission denied for language sql +SET SESSION AUTHORIZATION regressuser3; +SELECT testfunc1(5); -- fail +ERROR: function testfunc1(integer) does not exist +LINE 1: SELECT testfunc1(5); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +SELECT col1 FROM atest2 WHERE col2 = true; -- fail +ERROR: permission denied for relation atest2 +SELECT testfunc4(true); -- ok +ERROR: function testfunc4(boolean) does not exist +LINE 1: SELECT testfunc4(true); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +SET SESSION AUTHORIZATION regressuser4; +SELECT testfunc1(5); -- ok +ERROR: function testfunc1(integer) does not exist +LINE 1: SELECT testfunc1(5); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +DROP FUNCTION testfunc1(int); -- fail +ERROR: function testfunc1(integer) does not exist +\c - +DROP FUNCTION testfunc1(int); -- ok +ERROR: function testfunc1(integer) does not exist +-- restore to sanity +GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC; +-- truncate +SET SESSION AUTHORIZATION regressuser5; +TRUNCATE atest2; -- ok +TRUNCATE atest3; -- fail +ERROR: permission denied for relation atest3 +-- has_table_privilege function +-- bad-input checks +select has_table_privilege(NULL,'pg_authid','select'); + has_table_privilege +--------------------- + +(1 row) + +select has_table_privilege('pg_shad','select'); +ERROR: relation "pg_shad" does not exist +select has_table_privilege('nosuchuser','pg_authid','select'); +ERROR: role "nosuchuser" does not exist +select has_table_privilege('pg_authid','sel'); +ERROR: unrecognized privilege type: "sel" +select has_table_privilege(-999999,'pg_authid','update'); +ERROR: role with OID 4293967297 does not exist +select has_table_privilege(1,'select'); + has_table_privilege +--------------------- + +(1 row) + +-- superuser +\c - +select has_table_privilege(current_user,'pg_authid','select'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(current_user,'pg_authid','insert'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.oid,'pg_authid','update') +from (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.oid,'pg_authid','delete') +from (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +-- 'rule' privilege no longer exists, but for backwards compatibility +-- has_table_privilege still recognizes the keyword and says FALSE +select has_table_privilege(current_user,t1.oid,'rule') +from (select oid from pg_class where relname = 'pg_authid') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'pg_authid') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.oid,t1.oid,'select') +from (select oid from pg_class where relname = 'pg_authid') as t1, + (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.oid,t1.oid,'insert') +from (select oid from pg_class where relname = 'pg_authid') as t1, + (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege('pg_authid','update'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege('pg_authid','delete'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege('pg_authid','truncate'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'pg_authid') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'pg_authid') as t1; + has_table_privilege +--------------------- + t +(1 row) + +-- non-superuser +SET SESSION AUTHORIZATION regressuser3; +select has_table_privilege(current_user,'pg_class','select'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(current_user,'pg_class','insert'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.oid,'pg_class','update') +from (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.oid,'pg_class','delete') +from (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'pg_class') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.oid,t1.oid,'select') +from (select oid from pg_class where relname = 'pg_class') as t1, + (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.oid,t1.oid,'insert') +from (select oid from pg_class where relname = 'pg_class') as t1, + (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('pg_class','update'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('pg_class','delete'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('pg_class','truncate'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'pg_class') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'pg_class') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,'atest1','select'); + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(current_user,'atest1','insert'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.oid,'atest1','update') +from (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.oid,'atest1','delete') +from (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(current_user,t1.oid,'references') +from (select oid from pg_class where relname = 'atest1') as t1; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t2.oid,t1.oid,'select') +from (select oid from pg_class where relname = 'atest1') as t1, + (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t2.oid,t1.oid,'insert') +from (select oid from pg_class where relname = 'atest1') as t1, + (select oid from pg_roles where rolname = current_user) as t2; + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('atest1','update'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('atest1','delete'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege('atest1','truncate'); + has_table_privilege +--------------------- + f +(1 row) + +select has_table_privilege(t1.oid,'select') +from (select oid from pg_class where relname = 'atest1') as t1; + has_table_privilege +--------------------- + t +(1 row) + +select has_table_privilege(t1.oid,'trigger') +from (select oid from pg_class where relname = 'atest1') as t1; + has_table_privilege +--------------------- + f +(1 row) + +-- Grant options +SET SESSION AUTHORIZATION regressuser1; +CREATE TABLE atest4 (a int); +GRANT SELECT ON atest4 TO regressuser2 WITH GRANT OPTION; +GRANT UPDATE ON atest4 TO regressuser2; +GRANT SELECT ON atest4 TO GROUP regressgroup1 WITH GRANT OPTION; +SET SESSION AUTHORIZATION regressuser2; +GRANT SELECT ON atest4 TO regressuser3; +GRANT UPDATE ON atest4 TO regressuser3; -- fail +WARNING: no privileges were granted for "atest4" +SET SESSION AUTHORIZATION regressuser1; +REVOKE SELECT ON atest4 FROM regressuser3; -- does nothing +SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- true + has_table_privilege +--------------------- + t +(1 row) + +REVOKE SELECT ON atest4 FROM regressuser2; -- fail +ERROR: dependent privileges exist +HINT: Use CASCADE to revoke them too. +REVOKE GRANT OPTION FOR SELECT ON atest4 FROM regressuser2 CASCADE; -- ok +SELECT has_table_privilege('regressuser2', 'atest4', 'SELECT'); -- true + has_table_privilege +--------------------- + t +(1 row) + +SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- false + has_table_privilege +--------------------- + f +(1 row) + +SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION'); -- true + has_table_privilege +--------------------- + t +(1 row) + +-- has_sequence_privilege tests +\c - +CREATE SEQUENCE x_seq; +GRANT USAGE on x_seq to regressuser2; +SELECT has_sequence_privilege('regressuser1', 'atest1', 'SELECT'); +ERROR: "atest1" is not a sequence +SELECT has_sequence_privilege('regressuser1', 'x_seq', 'INSERT'); +ERROR: unrecognized privilege type: "INSERT" +SELECT has_sequence_privilege('regressuser1', 'x_seq', 'SELECT'); + has_sequence_privilege +------------------------ + f +(1 row) + +SET SESSION AUTHORIZATION regressuser2; +SELECT has_sequence_privilege('x_seq', 'USAGE'); + has_sequence_privilege +------------------------ + t +(1 row) + +-- largeobject privilege tests +\c - +SET SESSION AUTHORIZATION regressuser1; +SELECT lo_create(1001); + lo_create +----------- + 1001 +(1 row) + +SELECT lo_create(1002); + lo_create +----------- + 1002 +(1 row) + +SELECT lo_create(1003); + lo_create +----------- + 1003 +(1 row) + +SELECT lo_create(1004); + lo_create +----------- + 1004 +(1 row) + +SELECT lo_create(1005); + lo_create +----------- + 1005 +(1 row) + +GRANT ALL ON LARGE OBJECT 1001 TO PUBLIC; +GRANT SELECT ON LARGE OBJECT 1003 TO regressuser2; +GRANT SELECT,UPDATE ON LARGE OBJECT 1004 TO regressuser2; +GRANT ALL ON LARGE OBJECT 1005 TO regressuser2; +GRANT SELECT ON LARGE OBJECT 1005 TO regressuser2 WITH GRANT OPTION; +GRANT SELECT, INSERT ON LARGE OBJECT 1001 TO PUBLIC; -- to be failed +ERROR: invalid privilege type INSERT for large object +GRANT SELECT, UPDATE ON LARGE OBJECT 1001 TO nosuchuser; -- to be failed +ERROR: role "nosuchuser" does not exist +GRANT SELECT, UPDATE ON LARGE OBJECT 999 TO PUBLIC; -- to be failed +ERROR: large object 999 does not exist +\c - +SET SESSION AUTHORIZATION regressuser2; +SELECT lo_create(2001); + lo_create +----------- + 2001 +(1 row) + +SELECT lo_create(2002); + lo_create +----------- + 2002 +(1 row) + +SELECT loread(lo_open(1001, x'40000'::int), 32); + loread +-------- + \x +(1 row) + +SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied +ERROR: permission denied for large object 1002 +SELECT loread(lo_open(1003, x'40000'::int), 32); + loread +-------- + \x +(1 row) + +SELECT loread(lo_open(1004, x'40000'::int), 32); + loread +-------- + \x +(1 row) + +SELECT lowrite(lo_open(1001, x'20000'::int), 'abcd'); + lowrite +--------- + 4 +(1 row) + +SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied +ERROR: permission denied for large object 1002 +SELECT lowrite(lo_open(1003, x'20000'::int), 'abcd'); -- to be denied +ERROR: permission denied for large object 1003 +SELECT lowrite(lo_open(1004, x'20000'::int), 'abcd'); + lowrite +--------- + 4 +(1 row) + +GRANT SELECT ON LARGE OBJECT 1005 TO regressuser3; +GRANT UPDATE ON LARGE OBJECT 1006 TO regressuser3; -- to be denied +ERROR: large object 1006 does not exist +REVOKE ALL ON LARGE OBJECT 2001, 2002 FROM PUBLIC; +GRANT ALL ON LARGE OBJECT 2001 TO regressuser3; +SELECT lo_unlink(1001); -- to be denied +ERROR: must be owner of large object 1001 +SELECT lo_unlink(2002); + lo_unlink +----------- + 1 +(1 row) + +\c - +-- confirm ACL setting +SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata; + oid | ownername | lomacl +------+--------------+------------------------------------------------------------------------------------------ + 1002 | regressuser1 | + 1001 | regressuser1 | {regressuser1=rw/regressuser1,=rw/regressuser1} + 1003 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r/regressuser1} + 1004 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=rw/regressuser1} + 1005 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r*w/regressuser1,regressuser3=r/regressuser2} + 2001 | regressuser2 | {regressuser2=rw/regressuser2,regressuser3=rw/regressuser2} +(6 rows) + +SET SESSION AUTHORIZATION regressuser3; +SELECT loread(lo_open(1001, x'40000'::int), 32); + loread +------------ + \x61626364 +(1 row) + +SELECT loread(lo_open(1003, x'40000'::int), 32); -- to be denied +ERROR: permission denied for large object 1003 +SELECT loread(lo_open(1005, x'40000'::int), 32); + loread +-------- + \x +(1 row) + +SELECT lo_truncate(lo_open(1005, x'20000'::int), 10); -- to be denied +ERROR: permission denied for large object 1005 +SELECT lo_truncate(lo_open(2001, x'20000'::int), 10); + lo_truncate +------------- + 0 +(1 row) + +-- compatibility mode in largeobject permission +\c - +SET lo_compat_privileges = false; -- default setting +SET SESSION AUTHORIZATION regressuser4; +SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied +ERROR: permission denied for large object 1002 +SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied +ERROR: permission denied for large object 1002 +SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); -- to be denied +ERROR: permission denied for large object 1002 +SELECT lo_unlink(1002); -- to be denied +ERROR: must be owner of large object 1002 +SELECT lo_export(1001, '/dev/null'); -- to be denied +ERROR: must be superuser to use server-side lo_export() +HINT: Anyone can use the client-side lo_export() provided by libpq. +\c - +SET lo_compat_privileges = true; -- compatibility mode +SET SESSION AUTHORIZATION regressuser4; +SELECT loread(lo_open(1002, x'40000'::int), 32); + loread +-------- + \x +(1 row) + +SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); + lowrite +--------- + 4 +(1 row) + +SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); + lo_truncate +------------- + 0 +(1 row) + +SELECT lo_unlink(1002); + lo_unlink +----------- + 1 +(1 row) + +SELECT lo_export(1001, '/dev/null'); -- to be denied +ERROR: must be superuser to use server-side lo_export() +HINT: Anyone can use the client-side lo_export() provided by libpq. +-- don't allow unpriv users to access pg_largeobject contents +\c - +SELECT * FROM pg_largeobject LIMIT 0; + loid | pageno | data +------+--------+------ +(0 rows) + +SET SESSION AUTHORIZATION regressuser1; +SELECT * FROM pg_largeobject LIMIT 0; -- to be denied +ERROR: permission denied for relation pg_largeobject +-- test default ACLs +\c - +CREATE SCHEMA testns; +GRANT ALL ON SCHEMA testns TO regressuser1; +CREATE TABLE testns.acltest1 (x int); +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'SELECT'); -- no + has_table_privilege +--------------------- + f +(1 row) + +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'INSERT'); -- no + has_table_privilege +--------------------- + f +(1 row) + +ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT SELECT ON TABLES TO public; +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'SELECT'); -- no + has_table_privilege +--------------------- + f +(1 row) + +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'INSERT'); -- no + has_table_privilege +--------------------- + f +(1 row) + +DROP TABLE testns.acltest1; +CREATE TABLE testns.acltest1 (x int); +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'SELECT'); -- yes + has_table_privilege +--------------------- + t +(1 row) + +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'INSERT'); -- no + has_table_privilege +--------------------- + f +(1 row) + +ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT INSERT ON TABLES TO regressuser1; +DROP TABLE testns.acltest1; +CREATE TABLE testns.acltest1 (x int); +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'SELECT'); -- yes + has_table_privilege +--------------------- + t +(1 row) + +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'INSERT'); -- yes + has_table_privilege +--------------------- + t +(1 row) + +ALTER DEFAULT PRIVILEGES IN SCHEMA testns REVOKE INSERT ON TABLES FROM regressuser1; +DROP TABLE testns.acltest1; +CREATE TABLE testns.acltest1 (x int); +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'SELECT'); -- yes + has_table_privilege +--------------------- + t +(1 row) + +SELECT has_table_privilege('regressuser1', 'testns.acltest1', 'INSERT'); -- no + has_table_privilege +--------------------- + f +(1 row) + +ALTER DEFAULT PRIVILEGES FOR ROLE regressuser1 REVOKE EXECUTE ON FUNCTIONS FROM public; +SET ROLE regressuser1; +CREATE FUNCTION testns.foo() RETURNS int AS 'select 1' LANGUAGE sql; +ERROR: stable and volatile not yet supported, function volatility has to be immutable +SELECT has_function_privilege('regressuser2', 'testns.foo()', 'EXECUTE'); -- no +ERROR: function "testns.foo()" does not exist +ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT EXECUTE ON FUNCTIONS to public; +DROP FUNCTION testns.foo(); +ERROR: function testns.foo() does not exist +CREATE FUNCTION testns.foo() RETURNS int AS 'select 1' LANGUAGE sql; +ERROR: stable and volatile not yet supported, function volatility has to be immutable +SELECT has_function_privilege('regressuser2', 'testns.foo()', 'EXECUTE'); -- yes +ERROR: function "testns.foo()" does not exist +DROP FUNCTION testns.foo(); +ERROR: function testns.foo() does not exist +RESET ROLE; +SELECT count(*) + FROM pg_default_acl d LEFT JOIN pg_namespace n ON defaclnamespace = n.oid + WHERE nspname = 'testns'; + count +------- + 2 +(1 row) + +DROP SCHEMA testns CASCADE; +NOTICE: drop cascades to table testns.acltest1 +SELECT d.* -- check that entries went away + FROM pg_default_acl d LEFT JOIN pg_namespace n ON defaclnamespace = n.oid + WHERE nspname IS NULL AND defaclnamespace != 0; + defaclrole | defaclnamespace | defaclobjtype | defaclacl +------------+-----------------+---------------+----------- +(0 rows) + +-- Grant on all objects of given type in a schema +\c - +CREATE SCHEMA testns; +CREATE TABLE testns.t1 (f1 int); +CREATE TABLE testns.t2 (f1 int); +SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- false + has_table_privilege +--------------------- + f +(1 row) + +GRANT ALL ON ALL TABLES IN SCHEMA testns TO regressuser1; +SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- true + has_table_privilege +--------------------- + t +(1 row) + +SELECT has_table_privilege('regressuser1', 'testns.t2', 'SELECT'); -- true + has_table_privilege +--------------------- + t +(1 row) + +REVOKE ALL ON ALL TABLES IN SCHEMA testns FROM regressuser1; +SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- false + has_table_privilege +--------------------- + f +(1 row) + +SELECT has_table_privilege('regressuser1', 'testns.t2', 'SELECT'); -- false + has_table_privilege +--------------------- + f +(1 row) + +CREATE FUNCTION testns.testfunc(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql; +SELECT has_function_privilege('regressuser1', 'testns.testfunc(int)', 'EXECUTE'); -- true by default + has_function_privilege +------------------------ + t +(1 row) + +REVOKE ALL ON ALL FUNCTIONS IN SCHEMA testns FROM PUBLIC; +SELECT has_function_privilege('regressuser1', 'testns.testfunc(int)', 'EXECUTE'); -- false + has_function_privilege +------------------------ + f +(1 row) + +SET client_min_messages TO 'warning'; +DROP SCHEMA testns CASCADE; +RESET client_min_messages; +-- clean up +\c +drop sequence x_seq; +DROP FUNCTION testfunc2(int); +ERROR: function testfunc2(integer) does not exist +DROP FUNCTION testfunc4(boolean); +ERROR: function testfunc4(boolean) does not exist +DROP VIEW atestv1; +ERROR: view "atestv1" does not exist +DROP VIEW atestv2; +ERROR: view "atestv2" does not exist +-- this should cascade to drop atestv4 +DROP VIEW atestv3 CASCADE; +NOTICE: drop cascades to view atestv4 +ERROR: view "atestv3" does not exist +-- this should complain "does not exist" +DROP VIEW atestv4; +ERROR: view "atestv4" does not exist +DROP TABLE atest1; +ERROR: cannot drop table atest1 because other objects depend on it +DETAIL: view atestv1 depends on table atest1 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP TABLE atest2; +ERROR: cannot drop table atest2 because other objects depend on it +DETAIL: view atestv2 depends on table atest2 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP TABLE atest3; +ERROR: cannot drop table atest3 because other objects depend on it +DETAIL: view atestv3 depends on table atest3 +view atestv4 depends on view atestv3 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP TABLE atest4; +DROP TABLE atest5; +DROP TABLE atest6; +DROP TABLE atestc; +ERROR: table "atestc" does not exist +DROP TABLE atestp1; +DROP TABLE atestp2; +SELECT lo_unlink(oid) FROM pg_largeobject_metadata; + lo_unlink +----------- + 1 + 1 + 1 + 1 + 1 +(5 rows) + +DROP GROUP regressgroup1; +DROP GROUP regressgroup2; +ERROR: role "regressgroup2" cannot be dropped because some objects depend on it +DETAIL: privileges for table atest3 +-- these are needed to clean up permissions +REVOKE USAGE ON LANGUAGE sql FROM regressuser1; +DROP OWNED BY regressuser1; +ERROR: cannot drop desired object(s) because other objects depend on them +DETAIL: view atestv1 depends on table atest1 +view atestv2 depends on table atest2 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP USER regressuser1; +ERROR: role "regressuser1" cannot be dropped because some objects depend on it +DETAIL: owner of default privileges on new functions belonging to role regressuser1 +owner of table atest2 +owner of table atest1 +DROP USER regressuser2; +ERROR: role "regressuser2" cannot be dropped because some objects depend on it +DETAIL: privileges for view atestv4 +privileges for view atestv2 +privileges for table atest2 +privileges for table atest1 +DROP USER regressuser3; +ERROR: role "regressuser3" cannot be dropped because some objects depend on it +DETAIL: owner of view atestv3 +owner of view atestv2 +owner of view atestv1 +owner of table atest3 +privileges for table atest2 +privileges for table atest1 +DROP USER regressuser4; +ERROR: role "regressuser4" cannot be dropped because some objects depend on it +DETAIL: owner of view atestv4 +privileges for view atestv3 +privileges for view atestv1 +privileges for table atest2 +privileges for table atest1 +DROP USER regressuser5; +ERROR: role "regressuser5" cannot be dropped because some objects depend on it +DETAIL: privileges for table atest2 +DROP USER regressuser6; +ERROR: role "regressuser6" does not exist ----------------------------------------------------------------------- Summary of changes: .../expected/{privileges.out => privileges_1.out} | 166 +++++++++++++------- 1 files changed, 107 insertions(+), 59 deletions(-) copy src/test/regress/expected/{privileges.out => privileges_1.out} (87%) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-25 17:03:49
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 796bf6e4b113d356b7d725daa71d62835faf9c68 (commit) from ca673e251cd252aa997c9ac51b8f90d2788e8bac (commit) - Log ----------------------------------------------------------------- commit 796bf6e4b113d356b7d725daa71d62835faf9c68 Author: Michael P <mic...@us...> Date: Sat Mar 26 02:02:14 2011 +0900 Fix for regression test create type Postgres-XC does not support TEMP tables, so this output is correct. diff --git a/src/test/regress/expected/create_type_1.out b/src/test/regress/expected/create_type_1.out new file mode 100644 index 0000000..9317dd9 --- /dev/null +++ b/src/test/regress/expected/create_type_1.out @@ -0,0 +1,118 @@ +-- +-- CREATE_TYPE +-- +-- +-- Note: widget_in/out were created in create_function_1, without any +-- prior shell-type creation. These commands therefore complete a test +-- of the "old style" approach of making the functions first. +-- +CREATE TYPE widget ( + internallength = 24, + input = widget_in, + output = widget_out, + typmod_in = numerictypmodin, + typmod_out = numerictypmodout, + alignment = double +); +CREATE TYPE city_budget ( + internallength = 16, + input = int44in, + output = int44out, + element = int4, + category = 'x', -- just to verify the system will take it + preferred = true -- ditto +); +-- Test creation and destruction of shell types +CREATE TYPE shell; +CREATE TYPE shell; -- fail, type already present +ERROR: type "shell" already exists +DROP TYPE shell; +DROP TYPE shell; -- fail, type not exist +ERROR: type "shell" does not exist +-- +-- Test type-related default values (broken in releases before PG 7.2) +-- +-- This part of the test also exercises the "new style" approach of making +-- a shell type and then filling it in. +-- +CREATE TYPE int42; +CREATE TYPE text_w_default; +-- Make dummy I/O routines using the existing internal support for int4, text +CREATE FUNCTION int42_in(cstring) + RETURNS int42 + AS 'int4in' + LANGUAGE internal STRICT; +NOTICE: return type int42 is only a shell +CREATE FUNCTION int42_out(int42) + RETURNS cstring + AS 'int4out' + LANGUAGE internal STRICT; +NOTICE: argument type int42 is only a shell +CREATE FUNCTION text_w_default_in(cstring) + RETURNS text_w_default + AS 'textin' + LANGUAGE internal STRICT; +NOTICE: return type text_w_default is only a shell +CREATE FUNCTION text_w_default_out(text_w_default) + RETURNS cstring + AS 'textout' + LANGUAGE internal STRICT; +NOTICE: argument type text_w_default is only a shell +CREATE TYPE int42 ( + internallength = 4, + input = int42_in, + output = int42_out, + alignment = int4, + default = 42, + passedbyvalue +); +CREATE TYPE text_w_default ( + internallength = variable, + input = text_w_default_in, + output = text_w_default_out, + alignment = int4, + default = 'zippo' +); +CREATE TABLE default_test (f1 text_w_default, f2 int42); +INSERT INTO default_test DEFAULT VALUES; +SELECT * FROM default_test; + f1 | f2 +-------+---- + zippo | 42 +(1 row) + +-- Test stand-alone composite type +CREATE TYPE default_test_row AS (f1 text_w_default, f2 int42); +CREATE FUNCTION get_default_test() RETURNS SETOF default_test_row AS ' + SELECT * FROM default_test; +' LANGUAGE SQL; +SELECT * FROM get_default_test(); + f1 | f2 +-------+---- + zippo | 42 +(1 row) + +-- Test comments +COMMENT ON TYPE bad IS 'bad comment'; +ERROR: type "bad" does not exist +COMMENT ON TYPE default_test_row IS 'good comment'; +COMMENT ON TYPE default_test_row IS NULL; +-- Check shell type create for existing types +CREATE TYPE text_w_default; -- should fail +ERROR: type "text_w_default" already exists +DROP TYPE default_test_row CASCADE; +NOTICE: drop cascades to function get_default_test() +DROP TABLE default_test; +-- Check usage of typmod with a user-defined type +-- (we have borrowed numeric's typmod functions) +CREATE TEMP TABLE mytab (foo widget(42,13,7)); -- should fail +ERROR: invalid NUMERIC type modifier +LINE 1: CREATE TEMP TABLE mytab (foo widget(42,13,7)); + ^ +CREATE TEMP TABLE mytab (foo widget(42,13)); +ERROR: PG-XC does not yet support temporary tables +SELECT format_type(atttypid,atttypmod) FROM pg_attribute +WHERE attrelid = 'mytab'::regclass AND attnum > 0; +ERROR: relation "mytab" does not exist +LINE 2: WHERE attrelid = 'mytab'::regclass AND attnum > 0; + ^ ----------------------------------------------------------------------- Summary of changes: .../{create_type.out => create_type_1.out} | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) copy src/test/regress/expected/{create_type.out => create_type_1.out} (95%) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-25 15:09:26
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via ca673e251cd252aa997c9ac51b8f90d2788e8bac (commit) via 76f1d9cde238be026007d00a6af192b7f7ac4ce5 (commit) from 8f2f50bd72fd570de84518eaf39abbf464de7019 (commit) - Log ----------------------------------------------------------------- commit ca673e251cd252aa997c9ac51b8f90d2788e8bac Author: Michael P <mic...@us...> Date: Sat Mar 26 00:07:26 2011 +0900 Addition of a check when fetching tuples A strange crash was happening in xmlmap. diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 0f3551c..a200628 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -2881,11 +2881,19 @@ getlen_datanode(Tuplesortstate *state, int tapenum, bool eofOK) * the node number is stored in combiner->tapenodes[tapenum]. * If connection is inactive and no buffered data we have EOF condition */ - int nodenum = conn ? conn->nodenum : combiner->tapenodes[tapenum]; + int nodenum; unsigned int len = 0; ListCell *lc; ListCell *prev = NULL; + /* May it ever happen ?! */ + if (!conn && !combiner->tapenodes) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("Failed to fetch from data node cursor"))); + + nodenum = conn ? conn->nodenum : combiner->tapenodes[tapenum]; + /* * If there are buffered rows iterate over them and get first from * the requested tape commit 76f1d9cde238be026007d00a6af192b7f7ac4ce5 Author: Michael P <mic...@us...> Date: Fri Mar 25 21:12:42 2011 +0900 Fix for cache lookup bug for type With this fix, backend Datanode send back to remote Coordinator the type name and note the OID type to avoid type inconsistencies between nodes as Postgres-XC is a shared-nothing architecture. Patch idea is from Mason, base patch is from Benny, I just gathered all the ideas and improved the patch. diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index a5e811f..ad8c568 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -20,7 +20,10 @@ #include "libpq/pqformat.h" #include "tcop/pquery.h" #include "utils/lsyscache.h" - +#ifdef PGXC +#include "pgxc/pgxc.h" +#include "parser/parse_type.h" +#endif static void printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo); @@ -189,6 +192,20 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats) int32 atttypmod = attrs[i]->atttypmod; pq_sendstring(&buf, NameStr(attrs[i]->attname)); + +#ifdef PGXC + /* + * Send the type name from a Postgres-XC Datanode backend. + * This preserves from OID inconsistencies as architecture is shared nothing. + */ + if (IS_PGXC_DATANODE && IsConnFromCoord()) + { + char *typename; + typename = typeTypeName(typeidType(atttypid)); + pq_sendstring(&buf, typename); + } +#endif + /* column ID info appears in protocol 3.0 and up */ if (proto >= 3) { diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index d517899..95f23f3 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -35,6 +35,7 @@ #include "utils/snapmgr.h" #include "pgxc/locator.h" #include "pgxc/pgxc.h" +#include "parser/parse_type.h" #define END_QUERY_TIMEOUT 20 #define DATA_NODE_FETCH_SIZE 1 @@ -405,10 +406,10 @@ create_tuple_desc(char *msg_body, size_t len) for (i = 1; i <= nattr; i++) { AttrNumber attnum; - char *attname; + char *attname; + char *typname; Oid oidtypeid; int32 typmod; - uint32 n32; attnum = (AttrNumber) i; @@ -417,28 +418,31 @@ create_tuple_desc(char *msg_body, size_t len) attname = msg_body; msg_body += strlen(attname) + 1; + /* type name */ + typname = msg_body; + msg_body += strlen(typname) + 1; + /* table OID, ignored */ msg_body += 4; /* column no, ignored */ msg_body += 2; - /* data type */ - memcpy(&n32, msg_body, 4); - oidtypeid = ntohl(n32); + /* data type OID, ignored */ msg_body += 4; /* type len, ignored */ msg_body += 2; - /* type mod */ - memcpy(&n32, msg_body, 4); - typmod = ntohl(n32); + /* type mod, ignored */ msg_body += 4; /* PGXCTODO text/binary flag? */ msg_body += 2; + /* Get the OID type and mode type from typename */ + parseTypeString(typname, &oidtypeid, &typmod); + TupleDescInitEntry(result, attnum, attname, oidtypeid, typmod, 0); } return result; ----------------------------------------------------------------------- Summary of changes: src/backend/access/common/printtup.c | 19 ++++++++++++++++++- src/backend/pgxc/pool/execRemote.c | 20 ++++++++++++-------- src/backend/utils/sort/tuplesort.c | 10 +++++++++- 3 files changed, 39 insertions(+), 10 deletions(-) hooks/post-receive -- Postgres-XC |
From: Abbas B. <ga...@us...> - 2011-03-25 10:44:55
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via 8f2f50bd72fd570de84518eaf39abbf464de7019 (commit) from c696488cee189743e90303c52954f9e4d791e18c (commit) - Log ----------------------------------------------------------------- commit 8f2f50bd72fd570de84518eaf39abbf464de7019 Author: Abbas <abb...@en...> Date: Fri Mar 25 15:44:08 2011 +0500 Since the creation of unique indices is supposed to fail in XC hence this output is correct diff --git a/src/test/regress/expected/uuid_1.out b/src/test/regress/expected/uuid_1.out new file mode 100644 index 0000000..6a593be --- /dev/null +++ b/src/test/regress/expected/uuid_1.out @@ -0,0 +1,148 @@ +-- regression test for the uuid datatype +-- creating test tables +CREATE TABLE guid1 +( + guid_field UUID, + text_field TEXT DEFAULT(now()) +); +CREATE TABLE guid2 +( + guid_field UUID, + text_field TEXT DEFAULT(now()) +); +-- inserting invalid data tests +-- too long +INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111F'); +ERROR: invalid input syntax for uuid: "11111111-1111-1111-1111-111111111111F" +LINE 1: INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-111... + ^ +-- too short +INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-1111-11111111111}'); +ERROR: invalid input syntax for uuid: "{11111111-1111-1111-1111-11111111111}" +LINE 1: INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-11... + ^ +-- valid data but invalid format +INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-1111-111111111111'); +ERROR: invalid input syntax for uuid: "111-11111-1111-1111-1111-111111111111" +LINE 1: INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-11... + ^ +INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222 '); +ERROR: invalid input syntax for uuid: "{22222222-2222-2222-2222-222222222222 " +LINE 1: INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-22... + ^ +-- invalid data +INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G111-111111111111'); +ERROR: invalid input syntax for uuid: "11111111-1111-1111-G111-111111111111" +LINE 1: INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G11... + ^ +INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-1111-111111111111'); +ERROR: invalid input syntax for uuid: "11+11111-1111-1111-1111-111111111111" +LINE 1: INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-111... + ^ +--inserting three input formats +INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); +INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}'); +INSERT INTO guid1(guid_field) VALUES('3f3e3c3b3a3039383736353433a2313e'); +-- retrieving the inserted data +SELECT guid_field FROM guid1 ORDER BY guid_field; + guid_field +-------------------------------------- + 11111111-1111-1111-1111-111111111111 + 22222222-2222-2222-2222-222222222222 + 3f3e3c3b-3a30-3938-3736-353433a2313e +(3 rows) + +-- ordering test +SELECT guid_field FROM guid1 ORDER BY guid_field ASC; + guid_field +-------------------------------------- + 11111111-1111-1111-1111-111111111111 + 22222222-2222-2222-2222-222222222222 + 3f3e3c3b-3a30-3938-3736-353433a2313e +(3 rows) + +SELECT guid_field FROM guid1 ORDER BY guid_field DESC; + guid_field +-------------------------------------- + 3f3e3c3b-3a30-3938-3736-353433a2313e + 22222222-2222-2222-2222-222222222222 + 11111111-1111-1111-1111-111111111111 +(3 rows) + +-- = operator test +SELECT COUNT(*) FROM guid1 WHERE guid_field = '3f3e3c3b-3a30-3938-3736-353433a2313e'; + count +------- + 1 +(1 row) + +-- <> operator test +SELECT COUNT(*) FROM guid1 WHERE guid_field <> '11111111111111111111111111111111'; + count +------- + 2 +(1 row) + +-- < operator test +SELECT COUNT(*) FROM guid1 WHERE guid_field < '22222222-2222-2222-2222-222222222222'; + count +------- + 1 +(1 row) + +-- <= operator test +SELECT COUNT(*) FROM guid1 WHERE guid_field <= '22222222-2222-2222-2222-222222222222'; + count +------- + 2 +(1 row) + +-- > operator test +SELECT COUNT(*) FROM guid1 WHERE guid_field > '22222222-2222-2222-2222-222222222222'; + count +------- + 1 +(1 row) + +-- >= operator test +SELECT COUNT(*) FROM guid1 WHERE guid_field >= '22222222-2222-2222-2222-222222222222'; + count +------- + 2 +(1 row) + +-- btree and hash index creation test +CREATE INDEX guid1_btree ON guid1 USING BTREE (guid_field); +CREATE INDEX guid1_hash ON guid1 USING HASH (guid_field); +-- unique index test +CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE (guid_field); +ERROR: Cannot locally enforce a unique index on round robin distributed table. +-- should fail +INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); +-- check to see whether the new indexes are actually there +SELECT count(*) FROM pg_class WHERE relkind='i' AND relname LIKE 'guid%'; + count +------- + 2 +(1 row) + +-- populating the test tables with additional records +INSERT INTO guid1(guid_field) VALUES('44444444-4444-4444-4444-444444444444'); +INSERT INTO guid2(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); +INSERT INTO guid2(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}'); +INSERT INTO guid2(guid_field) VALUES('3f3e3c3b3a3039383736353433a2313e'); +-- join test +SELECT COUNT(*) FROM guid1 g1 INNER JOIN guid2 g2 ON g1.guid_field = g2.guid_field; + count +------- + 4 +(1 row) + +SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_field WHERE g2.guid_field IS NULL; + count +------- + 1 +(1 row) + +-- clean up +DROP TABLE guid1, guid2 CASCADE; ----------------------------------------------------------------------- Summary of changes: src/test/regress/expected/{uuid.out => uuid_1.out} | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) copy src/test/regress/expected/{uuid.out => uuid_1.out} (96%) hooks/post-receive -- Postgres-XC |
From: Michael P. <mic...@us...> - 2011-03-24 16:44:52
|
Project "Postgres-XC". The branch, merge_postgres_9_0_3 has been updated via c696488cee189743e90303c52954f9e4d791e18c (commit) from d12c17cc28433adedc44e63f5eb0f34b79c8523f (commit) - Log ----------------------------------------------------------------- commit c696488cee189743e90303c52954f9e4d791e18c Author: Michael P <mic...@us...> Date: Fri Mar 25 01:41:10 2011 +0900 Block DEFERRED constraints (DEFERRABLE) DEFERRED constraints are checked at transaction COMMIT. In a Postgres-XC transaction that involved DML failing on DEFERRED constraints, Datanodes return to Coordinator transaction errors, this was resulting in transaction partially committed in the cluster. In the case of pg_regress, test case constraints was putting the cluster in a stall state. IMMEDIATE constraints (default) are still available. diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index c8928f3..896ed43 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -3867,6 +3867,14 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) if (afterTriggers == NULL) return; +#ifdef PGXC + if (stmt->deferred) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Postgres-XC does not support DEFERRED constraints yet"), + errdetail("The feature is not currently supported"))); +#endif + /* * If in a subtransaction, and we didn't save the current state already, * save it so it can be restored if the subtransaction aborts. diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 6cfc1e6..21b5cfd 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -1345,6 +1345,15 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) index->deferrable = constraint->deferrable; index->initdeferred = constraint->initdeferred; +#ifdef PGXC + /* DEFERRABLE INITIALLY DEFERRED constraints are not supported in Postgres-XC */ + if (constraint->deferrable && constraint->initdeferred) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Postgres-XC does not support DEFERRED constraints yet"), + errdetail("The feature is not currently supported"))); +#endif + if (constraint->conname != NULL) index->idxname = pstrdup(constraint->conname); else @@ -2290,6 +2299,12 @@ transformConstraintAttrs(ParseState *pstate, List *constraintList) break; case CONSTR_ATTR_DEFERRED: +#ifdef PGXC + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Postgres-XC does not support DEFERRED constraints yet"), + errdetail("The feature is not currently supported"))); +#endif if (!SUPPORTS_ATTRS(lastprimarycon)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), ----------------------------------------------------------------------- Summary of changes: src/backend/commands/trigger.c | 8 ++++++++ src/backend/parser/parse_utilcmd.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 0 deletions(-) hooks/post-receive -- Postgres-XC |