diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index a206e53..08799ed 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -8,7 +8,7 @@ jobs:
fail-fast: false
matrix:
pg_version: ["11", "12", "13", "14", "15", "16", "17", "18"]
- from_version: ["2.2", "2.3"]
+ from_version: ["2.3", "2.4"]
steps:
- uses: actions/checkout@v6
- name: Remove default PostgreSQL
diff --git a/Makefile b/Makefile
index d4bea6c..5b3ebd2 100644
--- a/Makefile
+++ b/Makefile
@@ -10,8 +10,19 @@ DATA = pgl_ddl_deploy--1.0.sql pgl_ddl_deploy--1.0--1.1.sql \
pgl_ddl_deploy--2.0.sql pgl_ddl_deploy--2.0--2.1.sql \
pgl_ddl_deploy--2.1.sql pgl_ddl_deploy--2.1--2.2.sql \
pgl_ddl_deploy--2.2.sql pgl_ddl_deploy--2.2--2.3.sql \
- pgl_ddl_deploy--2.3.sql
-MODULES = pgl_ddl_deploy ddl_deparse
+ pgl_ddl_deploy--2.3.sql pgl_ddl_deploy--2.3--2.4.sql \
+ pgl_ddl_deploy--2.4.sql
+MODULES = ddl_deparse
+MODULE_big = pgl_ddl_deploy
+OBJS = postgres_deparse.11.o \
+ postgres_deparse.12.o \
+ postgres_deparse.13.o \
+ postgres_deparse.14.o \
+ postgres_deparse.15.o \
+ postgres_deparse.16.o \
+ postgres_deparse.17.o \
+ postgres_deparse.18.o \
+ pgl_ddl_deploy.o
REGRESS := 01_create_ext 02_setup 03_add_configs 04_deploy 04_deploy_update \
05_allowed 06_multi 07_edges 08_ignored \
@@ -52,7 +63,8 @@ REGRESS := 01_create_ext 02_setup 03_add_configs 04_deploy 04_deploy_update \
54_new_setup \
55_raise_message \
56_1_6_features \
- 57_native_features
+ 57_2_4_features \
+ 99_native_features
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
diff --git a/README.md b/README.md
index 7d54d60..b75c885 100644
--- a/README.md
+++ b/README.md
@@ -39,9 +39,10 @@ https://innovation.enova.com/pursuing-postgres-ddl-replication/
# Release Notes
-### Release 2.3
+### Release 2.4
Summary of changes:
-* Support for Postgres 17 & 18
+* Support for replicating index DDL
+* Prevent DDL that internally touches toast tables from being silently dropped
### Release 2.2
Summary of changes:
@@ -356,6 +357,11 @@ SQL statement with a single node `parsetree`) will be eligible for propagation.
be maintained by DDL replication. Thus only `ALTER TABLE`
statements are permitted here. This option is incompatible with
`include_schema_regex`.
+- `include_indexes`: if true, will replicate `CREATE INDEX`/`ALTER INDEX`/`DROP INDEX`
+ statements. This can be undesirable if the replica is intended to have different
+ configuration from the primary. Also, indexes cannot be created with `CREATE INDEX CONCURRENTLY`
+ and will therefore potentially block operations on the table, which can be problematic
+ if the replica is in active read usage.
- `queue_subscriber_failures`: if true, DDL will be allowed to fail on subscriber
without breaking replication, and queued for retry using function
`pgl_ddl_deploy.retry_all_subscriber_logs()`. This is useful for example if you
diff --git a/ddl_deparse.c b/ddl_deparse.c
index 794a78f..5fb3f2c 100644
--- a/ddl_deparse.c
+++ b/ddl_deparse.c
@@ -104,7 +104,7 @@ get_altertable_subcmdinfo(PG_FUNCTION_ARGS)
strtype = "ADD OIDS";
break;
case AT_AddOidsRecurse:
- strtype = "ADD OIDS (and recurse)";
+ strtype = "ADD OIDS";
break;
#endif
#if PG_VERSION_NUM >= 120000 && PG_VERSION_NUM < 180000
@@ -119,19 +119,19 @@ get_altertable_subcmdinfo(PG_FUNCTION_ARGS)
#endif
#if PG_VERSION_NUM < 160000
case AT_AddColumnRecurse:
- strtype = "ADD COLUMN (and recurse)";
+ strtype = "ADD COLUMN";
break;
case AT_DropColumnRecurse:
- strtype = "DROP COLUMN (and recurse)";
+ strtype = "DROP COLUMN";
break;
case AT_AddConstraintRecurse:
- strtype = "ADD CONSTRAINT (and recurse)";
+ strtype = "ADD CONSTRAINT";
break;
case AT_ValidateConstraintRecurse:
- strtype = "VALIDATE CONSTRAINT (and recurse)";
+ strtype = "VALIDATE CONSTRAINT";
break;
case AT_DropConstraintRecurse:
- strtype = "DROP CONSTRAINT (and recurse)";
+ strtype = "DROP CONSTRAINT";
break;
#endif
#if PG_VERSION_NUM >= 170000
diff --git a/debian/changelog b/debian/changelog
index 063f30a..c86b9f6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+pgl-ddl-deploy (2.4.0-1) unstable; urgency=medium
+
+ * Support for replicating index DDL
+ * Prevent DDL that internally touches toast tables from being silently dropped
+
+ -- Jacob Burroughs Wed, 17 Jun 2026 13:12:22 -0500
+
pgl-ddl-deploy (2.3.0-1) unstable; urgency=medium
* Support for Postgres 16
diff --git a/expected/05_allowed.out b/expected/05_allowed.out
index 2d9f4ea..ebe4f19 100644
--- a/expected/05_allowed.out
+++ b/expected/05_allowed.out
@@ -14,73 +14,73 @@ SELECT * FROM check_rep_tables();
(4 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test2 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test1 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test2 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test1 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
(4 rows)
ALTER TABLE foo ADD COLUMN bla TEXT;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test2 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test1 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test2 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test1 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
(8 rows)
INSERT INTO foo (bla) VALUES (1),(2),(3);
DROP TABLE foo CASCADE;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test2 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
(10 rows)
CREATE FUNCTION foo() RETURNS INT AS
@@ -89,64 +89,64 @@ SELECT 1;
$BODY$
LANGUAGE SQL STABLE;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+--------------------------------------+--------------------------------------
- test4 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test3 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test2 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test1 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+--------------------------------------+-----------------------------------------
+ test4 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test3 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test2 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test1 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test2 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
(10 rows)
ALTER FUNCTION foo() OWNER TO current_user;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
set_name | ddl_sql_raw | ddl_sql_sent
----------+---------------------------------------------+---------------------------------------------
- test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test2 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test1 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test4 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test3 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test2 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test1 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test2 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test1 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test4 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test3 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test2 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test1 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
(10 rows)
@@ -159,20 +159,20 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test2 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test1 | DROP FUNCTION foo(); | DROP FUNCTION foo();
- test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test2 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test1 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test4 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test3 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test2 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test1 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test4 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test3 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
(10 rows)
CREATE VIEW fooview AS
@@ -180,46 +180,46 @@ SELECT 1 AS myfield;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
set_name | ddl_sql_raw | ddl_sql_sent
----------+---------------------------------------------+---------------------------------------------
- test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test2 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test1 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test2 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test1 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
test4 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test3 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test2 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test1 | DROP FUNCTION foo(); | DROP FUNCTION foo();
- test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
+ test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
(10 rows)
ALTER VIEW fooview RENAME TO barview;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------+---------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------+---------------------------------------------
test4 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test3 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test2 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test1 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
- test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test2 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test1 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test2 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test1 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
test4 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test3 | DROP FUNCTION foo(); | DROP FUNCTION foo();
(10 rows)
DROP VIEW barview;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------+---------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------+---------------------------------------------
test4 | DROP VIEW barview; | DROP VIEW barview;
test3 | DROP VIEW barview; | DROP VIEW barview;
test2 | DROP VIEW barview; | DROP VIEW barview;
@@ -228,10 +228,10 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test2 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test1 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
- test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
(10 rows)
CREATE SEQUENCE foo;
@@ -313,34 +313,34 @@ SELECT * FROM check_rep_tables();
(8 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------+-------------------------------------------------
- test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test6 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test5 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test4 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test3 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test2 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test1 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------+--------------------------------------------------
+ test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test6 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test5 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test4 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test3 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test2 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test1 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
(10 rows)
ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------+-------------------------------------------------
- test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test6 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test5 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test4 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------+--------------------------------------------------
+ test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test6 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test5 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test4 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
(10 rows)
INSERT INTO foobar.foo (bla) VALUES (1),(2),(3);
@@ -356,8 +356,8 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test2 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test1 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
- test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
+ test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
(10 rows)
CREATE FUNCTION foobar.foo() RETURNS INT AS
@@ -366,48 +366,48 @@ SELECT 1;
$BODY$
LANGUAGE SQL STABLE;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------------+---------------------------------------------
- test8 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test7 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test6 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test5 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test4 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test3 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test2 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test1 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------------+------------------------------------------------
+ test8 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test7 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test6 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test5 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test4 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test3 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test2 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test1 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
test8 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test7 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
(10 rows)
@@ -416,24 +416,24 @@ ALTER FUNCTION foobar.foo() OWNER TO current_user;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
set_name | ddl_sql_raw | ddl_sql_sent
----------+----------------------------------------------------+----------------------------------------------------
- test8 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test7 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test6 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test5 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test4 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test3 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test2 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test1 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test8 | CREATE FUNCTION foobar.foo() RETURNS INT AS +| CREATE FUNCTION foobar.foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test7 | CREATE FUNCTION foobar.foo() RETURNS INT AS +| CREATE FUNCTION foobar.foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ test8 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test7 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test6 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test5 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test4 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test3 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test2 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test1 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test8 | CREATE FUNCTION foobar.foo() RETURNS INT AS +| CREATE FUNCTION foobar.foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test7 | CREATE FUNCTION foobar.foo() RETURNS INT AS +| CREATE FUNCTION foobar.foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
(10 rows)
DROP FUNCTION foobar.foo();
@@ -448,39 +448,39 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
test2 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
test1 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
- test8 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test7 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
+ test8 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test7 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
(10 rows)
CREATE VIEW foobar.fooview AS
SELECT 1 AS myfield;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------+-------------------------------
- test8 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test7 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test6 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test5 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test4 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test3 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test2 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test1 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------+----------------------------------------------------
+ test8 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test7 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test6 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test5 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test4 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test3 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test2 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test1 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
test8 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
test7 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
(10 rows)
ALTER VIEW foobar.fooview RENAME TO barview;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+----------------------------------------------+----------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+----------------------------------------------+----------------------------------------------------
test8 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
test7 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
test6 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
@@ -489,10 +489,10 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
test2 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
test1 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
- test8 | CREATE VIEW foobar.fooview AS +| CREATE VIEW foobar.fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test7 | CREATE VIEW foobar.fooview AS +| CREATE VIEW foobar.fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ test8 | CREATE VIEW foobar.fooview AS +| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test7 | CREATE VIEW foobar.fooview AS +| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
(10 rows)
DROP VIEW foobar.barview;
@@ -566,18 +566,18 @@ SELECT * FROM check_rep_tables();
(0 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------+-----------------------------
- test8 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test7 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test6 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test5 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test4 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test3 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test2 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test1 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test8 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
- test7 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------+------------------------------------
+ test8 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test7 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test6 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test5 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test4 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test3 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test2 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test1 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test8 | ALTER SEQUENCE foobar.foo RESTART; | ALTER SEQUENCE foobar.foo RESTART;
+ test7 | ALTER SEQUENCE foobar.foo RESTART; | ALTER SEQUENCE foobar.foo RESTART;
(10 rows)
SELECT * FROM pgl_ddl_deploy.unhandled;
diff --git a/expected/06_multi.out b/expected/06_multi.out
index ffc6786..2065aa5 100644
--- a/expected/06_multi.out
+++ b/expected/06_multi.out
@@ -19,18 +19,18 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------+-----------------------------
- test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test5 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test4 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test3 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test2 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test1 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test8 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test7 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------+---------------------------
+ test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test5 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test4 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test3 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test2 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test1 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test8 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test7 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
(10 rows)
SELECT set_name, ddl_sql_raw, command_tag, reason FROM pgl_ddl_deploy.unhandled ORDER BY id DESC LIMIT 10;
@@ -60,14 +60,14 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
COMMIT
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------------------+------------------------------------------------
- test7 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test5 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test3 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test1 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test3 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo(id int primary key);
- test1 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo(id int primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------------------+-----------------------------------------------
+ test7 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test5 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test1 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo (id int PRIMARY KEY);
+ test1 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo (id int PRIMARY KEY);
test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
@@ -106,14 +106,14 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------------------------------------------------------+-----------------------------------------------------------------------------
- test7 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test5 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test3 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test1 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test3 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;
- test1 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-----------------------------------------------------------------------------+------------------------------------------------------------------------------
+ test7 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test5 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test3 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test1 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test3 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;
+ test1 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;
test8 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test7 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test6 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
@@ -147,18 +147,18 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+----------------------------------------------+----------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+----------------------------------------------+-----------------------------------------------
test4 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test3 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test2 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test1 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
- test8 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test7 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test6 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test5 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test4 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test3 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
+ test8 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test6 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test5 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test4 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
(10 rows)
SELECT set_name, ddl_sql_raw, command_tag, reason FROM pgl_ddl_deploy.unhandled ORDER BY id DESC LIMIT 10;
diff --git a/expected/06_multi_1.out b/expected/06_multi_1.out
index 7f4c9f5..a9254db 100644
--- a/expected/06_multi_1.out
+++ b/expected/06_multi_1.out
@@ -23,18 +23,18 @@ CREATE TABLE
INSERT 0 3
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------+-----------------------------
- test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test5 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test4 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test3 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test2 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test1 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test8 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test7 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------+---------------------------
+ test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test5 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test4 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test3 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test2 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test1 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test8 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test7 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
(10 rows)
SELECT set_name, ddl_sql_raw, command_tag, reason FROM pgl_ddl_deploy.unhandled ORDER BY id DESC LIMIT 10;
@@ -68,14 +68,14 @@ BEGIN
CREATE TABLE
COMMIT
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------------------+------------------------------------------------
- test7 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test5 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test3 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test1 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test3 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo(id int primary key);
- test1 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo(id int primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------------------+-----------------------------------------------
+ test7 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test5 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test1 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo (id int PRIMARY KEY);
+ test1 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo (id int PRIMARY KEY);
test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
@@ -116,14 +116,14 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
CREATE TABLE
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------------------------------------------------------+-----------------------------------------------------------------------------
- test7 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test5 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test3 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test1 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test3 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;
- test1 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-----------------------------------------------------------------------------+------------------------------------------------------------------------------
+ test7 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test5 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test3 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test1 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test3 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;
+ test1 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;
test8 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test7 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test6 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
@@ -157,18 +157,18 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+----------------------------------------------+----------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+----------------------------------------------+-----------------------------------------------
test4 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test3 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test2 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test1 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
- test8 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test7 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test6 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test5 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test4 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test3 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
+ test8 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test6 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test5 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test4 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
(10 rows)
SELECT set_name, ddl_sql_raw, command_tag, reason FROM pgl_ddl_deploy.unhandled ORDER BY id DESC LIMIT 10;
diff --git a/expected/07_edges.out b/expected/07_edges.out
index 14a7b1f..f33dc69 100644
--- a/expected/07_edges.out
+++ b/expected/07_edges.out
@@ -5,18 +5,18 @@ CREATE TABLE foo (id SERIAL PRIMARY KEY);
--This is an edge case that currently can't be dealt with well with filtered replication.
ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------------------------------+------------------------------------------------------------------
- test8 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test7 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test6 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test5 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test4 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test3 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test2 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test1 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test4 | CREATE TABLE foo (id SERIAL PRIMARY KEY); | CREATE TABLE foo (id SERIAL PRIMARY KEY);
- test3 | CREATE TABLE foo (id SERIAL PRIMARY KEY); | CREATE TABLE foo (id SERIAL PRIMARY KEY);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------------------------------+-------------------------------------------------------------------
+ test8 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test7 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test6 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test5 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test4 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test3 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test2 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test1 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test4 | CREATE TABLE foo (id SERIAL PRIMARY KEY); | CREATE TABLE foo (id serial PRIMARY KEY);
+ test3 | CREATE TABLE foo (id SERIAL PRIMARY KEY); | CREATE TABLE foo (id serial PRIMARY KEY);
(10 rows)
DROP TABLE foobar.foo CASCADE;
diff --git a/expected/13_transaction.out b/expected/13_transaction.out
index c66b9ec..d1f4d78 100644
--- a/expected/13_transaction.out
+++ b/expected/13_transaction.out
@@ -15,24 +15,24 @@ SELECT * FROM check_rep_tables();
(4 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test2 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test1 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test2 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test1 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
test8 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
test7 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
test6 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
@@ -43,28 +43,28 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
ALTER TABLE foo ADD COLUMN bla TEXT;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test2 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test1 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test2 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test1 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
test8 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
test7 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
(10 rows)
@@ -72,24 +72,24 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
INSERT INTO foo (bla) VALUES (1),(2),(3);
DROP TABLE foo CASCADE;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test2 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
(10 rows)
CREATE TABLE foobar.foo(id serial primary key);
@@ -107,34 +107,34 @@ SELECT * FROM check_rep_tables();
(8 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------+-------------------------------------------------
- test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test6 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test5 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test4 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test3 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test2 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test1 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------+--------------------------------------------------
+ test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test6 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test5 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test4 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test3 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test2 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test1 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
(10 rows)
ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------+-------------------------------------------------
- test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test6 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test5 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test4 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------+--------------------------------------------------
+ test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test6 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test5 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test4 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
(10 rows)
INSERT INTO foobar.foo (bla) VALUES (1),(2),(3);
@@ -150,8 +150,8 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test2 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test1 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
- test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
+ test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
(10 rows)
COMMIT;
diff --git a/expected/15_new_set_behavior.out b/expected/15_new_set_behavior.out
index 2322c13..0bef49a 100644
--- a/expected/15_new_set_behavior.out
+++ b/expected/15_new_set_behavior.out
@@ -62,9 +62,9 @@ BEGIN;
INSERT INTO pgl_ddl_deploy.set_configs (set_name, include_only_repset_tables)
VALUES ('temp_1', TRUE);
SELECT create_tags, drop_tags FROM pgl_ddl_deploy.set_configs WHERE set_name = 'temp_1';
- create_tags | drop_tags
------------------+-----------
- {"ALTER TABLE"} |
+ create_tags | drop_tags
+-------------------------+-----------
+ {"ALTER TABLE",COMMENT} |
(1 row)
ROLLBACK;
diff --git a/expected/16_multi_set_tags.out b/expected/16_multi_set_tags.out
index 4f3d990..58fb130 100644
--- a/expected/16_multi_set_tags.out
+++ b/expected/16_multi_set_tags.out
@@ -11,11 +11,11 @@ FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
WHERE c.set_name = 'test1'
ORDER BY e.id DESC LIMIT 4;
- create_tags | set_name | ddl_sql_raw | ddl_sql_sent
---------------------------------------------------------------------------------------------------------------+----------+----------------------------------------------+----------------------------------------------
- {"CREATE VIEW","ALTER VIEW","CREATE FUNCTION","ALTER FUNCTION"} | test1 | CREATE VIEW viewer.vw_foo AS +| CREATE VIEW viewer.vw_foo AS +
- | | SELECT * FROM viewer.foo; | SELECT * FROM viewer.foo;
- {"ALTER TABLE","CREATE SEQUENCE","ALTER SEQUENCE","CREATE SCHEMA","CREATE TABLE","CREATE TYPE","ALTER TYPE"} | test1 | CREATE TABLE viewer.foo(id int primary key); | CREATE TABLE viewer.foo(id int primary key);
+ create_tags | set_name | ddl_sql_raw | ddl_sql_sent
+--------------------------------------------------------------------------------------------------------------+----------+----------------------------------------------+--------------------------------------------------------
+ {"CREATE VIEW","ALTER VIEW","CREATE FUNCTION","ALTER FUNCTION"} | test1 | CREATE VIEW viewer.vw_foo AS +| CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;
+ | | SELECT * FROM viewer.foo; |
+ {"ALTER TABLE","CREATE SEQUENCE","ALTER SEQUENCE","CREATE SCHEMA","CREATE TABLE","CREATE TYPE","ALTER TYPE"} | test1 | CREATE TABLE viewer.foo(id int primary key); | CREATE TABLE viewer.foo (id int PRIMARY KEY);
{"ALTER TABLE","CREATE SEQUENCE","ALTER SEQUENCE","CREATE SCHEMA","CREATE TABLE","CREATE TYPE","ALTER TYPE"} | test1 | CREATE SCHEMA viewer; | CREATE SCHEMA viewer;
{"ALTER TABLE","CREATE SEQUENCE","ALTER SEQUENCE","CREATE SCHEMA","CREATE TABLE","CREATE TYPE","ALTER TYPE"} | test1 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
(4 rows)
@@ -28,13 +28,13 @@ FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
WHERE c.set_name = 'test1'
ORDER BY e.id DESC LIMIT 4;
- drop_tags | set_name | ddl_sql_raw | ddl_sql_sent
-----------------------------------------------------------+----------+--------------------------------+--------------------------------
- {"DROP SCHEMA","DROP TABLE","DROP TYPE","DROP SEQUENCE"} | test1 | DROP SCHEMA viewer; | DROP SCHEMA viewer;
- {"DROP SCHEMA","DROP TABLE","DROP TYPE","DROP SEQUENCE"} | test1 | DROP TABLE viewer.foo CASCADE; | DROP TABLE viewer.foo CASCADE;
- {"DROP VIEW","DROP FUNCTION"} | test1 | DROP VIEW viewer.vw_foo; | DROP VIEW viewer.vw_foo;
- {"DROP VIEW","DROP FUNCTION"} | test1 | CREATE VIEW viewer.vw_foo AS +| CREATE VIEW viewer.vw_foo AS +
- | | SELECT * FROM viewer.foo; | SELECT * FROM viewer.foo;
+ drop_tags | set_name | ddl_sql_raw | ddl_sql_sent
+----------------------------------------------------------+----------+----------------------------------------------+--------------------------------------------------------
+ {"DROP SCHEMA","DROP TABLE","DROP TYPE","DROP SEQUENCE"} | test1 | DROP TABLE viewer.foo CASCADE; | DROP TABLE viewer.foo CASCADE;
+ {"DROP VIEW","DROP FUNCTION"} | test1 | DROP VIEW viewer.vw_foo; | DROP VIEW viewer.vw_foo;
+ {"DROP VIEW","DROP FUNCTION"} | test1 | CREATE VIEW viewer.vw_foo AS +| CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;
+ | | SELECT * FROM viewer.foo; |
+ {"DROP SCHEMA","DROP TABLE","DROP TYPE","DROP SEQUENCE"} | test1 | CREATE TABLE viewer.foo(id int primary key); | CREATE TABLE viewer.foo (id int PRIMARY KEY);
(4 rows)
SELECT * FROM pgl_ddl_deploy.exceptions;
diff --git a/expected/19_include_only_repset_tables_3.out b/expected/19_include_only_repset_tables_3.out
index e49e53c..0a53398 100644
--- a/expected/19_include_only_repset_tables_3.out
+++ b/expected/19_include_only_repset_tables_3.out
@@ -9,8 +9,8 @@ WHERE c.set_name LIKE 'my_special_tables%'
ORDER BY e.id DESC LIMIT 10;
create_tags | set_name | ddl_sql_raw | ddl_sql_sent
-----------------+---------------------+--------------------------------------------------+--------------------------------------------------
- {"ALTER TABLE"} | my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier TEXT;
- {"ALTER TABLE"} | my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy TEXT;
+ {"ALTER TABLE"} | my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier text;
+ {"ALTER TABLE"} | my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy text;
(2 rows)
--Test renaming which was missing in 1.2
@@ -34,8 +34,8 @@ WHERE c.set_name LIKE 'my_special_tables%' ORDER BY e.id DESC LIMIT 20;
my_special_tables_2 | ALTER TABLE special.bar RENAME COLUMN happier TO happierz; | ALTER TABLE special.bar RENAME COLUMN happier TO happierz;
my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN id TO id_2; | ALTER TABLE special.foo RENAME COLUMN id TO id_2;
my_special_tables_1 | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true); | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);
- my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy to happyz;
- my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier TEXT;
- my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy TEXT;
+ my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy TO happyz;
+ my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier text;
+ my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy text;
(9 rows)
diff --git a/expected/20_include_only_repset_tables_4.out b/expected/20_include_only_repset_tables_4.out
index a68836e..c54ca57 100644
--- a/expected/20_include_only_repset_tables_4.out
+++ b/expected/20_include_only_repset_tables_4.out
@@ -20,9 +20,9 @@ WHERE c.set_name LIKE 'my_special_tables%' ORDER BY e.id DESC LIMIT 10;
my_special_tables_2 | ALTER TABLE special.bar RENAME COLUMN happier TO happierz; | ALTER TABLE special.bar RENAME COLUMN happier TO happierz;
my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN id TO id_2; | ALTER TABLE special.foo RENAME COLUMN id TO id_2;
my_special_tables_1 | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true); | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);
- my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy to happyz;
- my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier TEXT;
- my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy TEXT;
+ my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy TO happyz;
+ my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier text;
+ my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy text;
(10 rows)
-- Test new subcommand functionality
@@ -56,8 +56,8 @@ INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
WHERE c.set_name LIKE 'my_special_tables%' ORDER BY e.id DESC LIMIT 10;
set_name | ddl_sql_raw | ddl_sql_sent
---------------------+--------------------------------------------------------------------------------+--------------------------------------------------------------------------------
- my_special_tables_1 | ALTER TABLE special.fooz ADD COLUMN bar_id INT; | ALTER TABLE special.fooz ADD COLUMN bar_id INT;
- my_special_tables_2 | ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2); | ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);
+ my_special_tables_1 | ALTER TABLE special.fooz ADD COLUMN bar_id INT; | ALTER TABLE special.fooz ADD COLUMN bar_id int;
+ my_special_tables_2 | ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2); | ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);
my_special_tables_1 | ALTER TABLE special.fooz DISABLE TRIGGER noop; | ALTER TABLE special.fooz DISABLE TRIGGER noop;
my_special_tables_2 | ALTER TABLE special.bar RENAME TO barz; | ALTER TABLE special.bar RENAME TO barz;
my_special_tables_1 | ALTER TABLE special.foo RENAME TO fooz; | ALTER TABLE special.foo RENAME TO fooz;
@@ -65,7 +65,7 @@ WHERE c.set_name LIKE 'my_special_tables%' ORDER BY e.id DESC LIMIT 10;
my_special_tables_2 | ALTER TABLE special.bar RENAME COLUMN happier TO happierz; | ALTER TABLE special.bar RENAME COLUMN happier TO happierz;
my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN id TO id_2; | ALTER TABLE special.foo RENAME COLUMN id TO id_2;
my_special_tables_1 | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true); | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);
- my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy to happyz;
+ my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy TO happyz;
(10 rows)
SET client_min_messages = warning;
diff --git a/expected/20_include_only_repset_tables_4_1.out b/expected/20_include_only_repset_tables_4_1.out
index 44f58f0..a68836e 100644
--- a/expected/20_include_only_repset_tables_4_1.out
+++ b/expected/20_include_only_repset_tables_4_1.out
@@ -45,11 +45,11 @@ LOG: Not processing DDL due to excluded subcommand(s): ENABLE TRIGGER: ALTER TA
-- This contains a tag we want to ignore but we can't separate out the parts - see the warning message
ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);
WARNING: Filtering out more than one subcommand in one ALTER TABLE is not supported.
- Allowing to proceed: Rejected: ADD CONSTRAINT (and recurse), SQL: ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);
+ Allowing to proceed: Rejected: ADD CONSTRAINT, SQL: ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);
ALTER TABLE special.fooz ADD COLUMN bar_id INT;
-- This one should be ignored as well
ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
-LOG: Not processing DDL due to excluded subcommand(s): ADD CONSTRAINT (and recurse): ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
+LOG: Not processing DDL due to excluded subcommand(s): ADD CONSTRAINT: ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
SELECT c.set_name, ddl_sql_raw, ddl_sql_sent
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
diff --git a/expected/22_is_deployed.out b/expected/22_is_deployed.out
index 7a6f736..c4df3f6 100644
--- a/expected/22_is_deployed.out
+++ b/expected/22_is_deployed.out
@@ -52,18 +52,18 @@ SELECT set_name, is_deployed FROM pgl_ddl_deploy.event_trigger_schema ORDER BY i
CREATE TABLE foobar (id serial primary key);
DROP TABLE foobar;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+----------------------------------+----------------------------------
- test4 | DROP SCHEMA special; | DROP SCHEMA special;
- test3 | DROP SCHEMA special; | DROP SCHEMA special;
- test2 | DROP SCHEMA special; | DROP SCHEMA special;
- test1 | DROP SCHEMA special; | DROP SCHEMA special;
- test4 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
- test3 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
- test2 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
- test1 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
- test4 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
- test3 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------
+ test4 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test3 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test2 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test1 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test4 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ test3 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ test2 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ test1 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ test4 | ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3); | ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
+ test3 | ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3); | ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
(10 rows)
--Re-deploy and check again what shows as deployed
@@ -108,11 +108,11 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP TABLE foobar CASCADE; | DROP TABLE foobar CASCADE;
test2 | DROP TABLE foobar CASCADE; | DROP TABLE foobar CASCADE;
test1 | DROP TABLE foobar CASCADE; | DROP TABLE foobar CASCADE;
- test4 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial primary key);
- test3 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial primary key);
- test2 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial primary key);
- test1 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial primary key);
- test4 | DROP SCHEMA special; | DROP SCHEMA special;
- test3 | DROP SCHEMA special; | DROP SCHEMA special;
+ test4 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial PRIMARY KEY);
+ test3 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial PRIMARY KEY);
+ test2 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial PRIMARY KEY);
+ test1 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial PRIMARY KEY);
+ test4 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test3 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
(10 rows)
diff --git a/expected/23_1_4_features.out b/expected/23_1_4_features.out
index 1352e6b..a484b74 100644
--- a/expected/23_1_4_features.out
+++ b/expected/23_1_4_features.out
@@ -63,17 +63,17 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.ddl_only_replication
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | ddl_only_replication
----------------+------------------------------------------------+------------------------------------------------+----------------------
- test_ddl_only | DROP TABLE duper.man; | DROP TABLE duper.man; | t
- test_ddl_only | DROP TABLE super.man CASCADE; | DROP TABLE super.man CASCADE; | f
- test_ddl_only | ALTER TABLE duper.man ADD COLUMN foo text; | ALTER TABLE duper.man ADD COLUMN foo text; | t
- test_ddl_only | ALTER TABLE super.man ADD COLUMN foo text; | ALTER TABLE super.man ADD COLUMN foo text; | f
- test_ddl_only | CREATE TABLE duper.man(id serial primary key); | CREATE TABLE duper.man(id serial primary key); | t
- test_ddl_only | CREATE SCHEMA duper; | CREATE SCHEMA duper; | t
- test_ddl_only | CREATE TABLE super.man(id serial primary key); | CREATE TABLE super.man(id serial primary key); | f
- test_ddl_only | CREATE SCHEMA super; | CREATE SCHEMA super; | f
- test4 | CREATE SCHEMA bla; | CREATE SCHEMA bla; | f
- test3 | CREATE SCHEMA bla; | CREATE SCHEMA bla; | f
+ set_name | ddl_sql_raw | ddl_sql_sent | ddl_only_replication
+---------------+------------------------------------------------+-------------------------------------------------+----------------------
+ test_ddl_only | DROP TABLE duper.man; | DROP TABLE duper.man; | t
+ test_ddl_only | DROP TABLE super.man CASCADE; | DROP TABLE super.man CASCADE; | f
+ test_ddl_only | ALTER TABLE duper.man ADD COLUMN foo text; | ALTER TABLE duper.man ADD COLUMN foo text; | t
+ test_ddl_only | ALTER TABLE super.man ADD COLUMN foo text; | ALTER TABLE super.man ADD COLUMN foo text; | f
+ test_ddl_only | CREATE TABLE duper.man(id serial primary key); | CREATE TABLE duper.man (id serial PRIMARY KEY); | t
+ test_ddl_only | CREATE SCHEMA duper; | CREATE SCHEMA duper; | t
+ test_ddl_only | CREATE TABLE super.man(id serial primary key); | CREATE TABLE super.man (id serial PRIMARY KEY); | f
+ test_ddl_only | CREATE SCHEMA super; | CREATE SCHEMA super; | f
+ test4 | CREATE SCHEMA bla; | CREATE SCHEMA bla; | f
+ test3 | CREATE SCHEMA bla; | CREATE SCHEMA bla; | f
(10 rows)
diff --git a/expected/24_sub_retries.out b/expected/24_sub_retries.out
index ddeb8d8..aeef9bc 100644
--- a/expected/24_sub_retries.out
+++ b/expected/24_sub_retries.out
@@ -2,36 +2,36 @@
--If adding new tests, it is best to keep this file as the last test before cleanup.
SET client_min_messages = warning;
SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(message::text, 'p_pid := (\d+)', 'p_pid := ?'), 'p_provider_name := (NULL|''\w+'')', 'p_provider_name := ?'), 'p_driver := (''\w+'')', 'p_driver := ?') as message FROM all_queues() WHERE NOT message::text LIKE '%notify_subscription_refresh%' ORDER BY queued_at;
- pubnames | message_type | message
------------------------+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n /***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n /***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ pubnames | message_type | message
+-----------------------+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER VIEW fooview RENAME TO barview;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER VIEW fooview RENAME TO barview;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER VIEW fooview RENAME TO barview;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -60,22 +60,22 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA foobar;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -84,22 +84,22 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foobar.foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foobar.foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foobar.foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -108,14 +108,14 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foobar.foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foobar.foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foobar.foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW foobar.fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER VIEW foobar.fooview RENAME TO barview;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW foobar.fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER VIEW foobar.fooview RENAME TO barview;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW foobar.fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER VIEW foobar.fooview RENAME TO barview;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -156,14 +156,6 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SEQUENCE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SEQUENCE foobar.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SEQUENCE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SEQUENCE foobar.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SEQUENCE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SEQUENCE foobar.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA foobar;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA foobar;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -172,12 +164,12 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA foobar;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ CREATE TABLE foo(id int primary key); $PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo(id int primary key); \n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foobar.foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ CREATE TABLE foobar.foo(id int primary key); $PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foobar.foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key); \n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foobar.foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ CREATE TABLE foobar.foo(id int primary key); $PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foobar.foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key); \n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -190,48 +182,48 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo, foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo, foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo, foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo, foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo, foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo, foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo, foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo, foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -256,34 +248,34 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n /***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n /***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -296,14 +288,14 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA viewer;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA viewer;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA viewer;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE viewer.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE viewer.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE viewer.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE viewer.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE viewer.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE viewer.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE viewer.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE viewer.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP VIEW viewer.vw_foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP VIEW viewer.vw_foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP VIEW viewer.vw_foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP VIEW viewer.vw_foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP VIEW viewer.vw_foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP VIEW viewer.vw_foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -312,46 +304,42 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE viewer.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE viewer.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE viewer.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE viewer.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE viewer.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE viewer.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA viewer;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA viewer;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA viewer;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA viewer;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA special;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA special;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA special;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA special;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.foo (id serial primary key, foo text, bar text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.foo (id serial primary key, foo text, bar text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial primary key, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.bar (id serial primary key, super text, man text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial primary key, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.bar (id serial primary key, super text, man text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial primary key, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.bar (id serial primary key, super text, man text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial primary key, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.bar (id serial primary key, super text, man text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD COLUMN happy TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD COLUMN happy TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_2'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 16,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar ADD COLUMN happier TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar ADD COLUMN happier TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME COLUMN happy to happyz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME COLUMN happy to happyz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD COLUMN happy text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD COLUMN happy text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_2'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 16,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar ADD COLUMN happier text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar ADD COLUMN happier text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME COLUMN happy TO happyz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME COLUMN happy TO happyz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -377,10 +365,10 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar RENAME TO barz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar RENAME TO barz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar RENAME TO barz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar RENAME TO barz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar RENAME TO barz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar RENAME TO barz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz DISABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz DISABLE TRIGGER noop;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz DISABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz DISABLE TRIGGER noop;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz DISABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz DISABLE TRIGGER noop;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -390,16 +378,16 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ENABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ENABLE TRIGGER noop;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ENABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ENABLE TRIGGER noop;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ENABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ENABLE TRIGGER noop;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 16,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD COLUMN bar_id INT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD COLUMN bar_id INT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 16,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id int;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id int;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id int;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD COLUMN bar_id int;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD COLUMN bar_id int;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -412,14 +400,10 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE special.barz CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE special.barz CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE special.barz CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE special.barz CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE special.barz CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE special.barz CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA special;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA special;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA special;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA special;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar (id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar (id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar (id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar (id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -429,14 +413,14 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA bla;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE SCHEMA bla;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA bla;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE SCHEMA bla;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA super;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE SCHEMA super;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'super',\n p_relname := 'man_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE super.man(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE TABLE super.man(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'super',\n p_relname := 'man_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE super.man (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE TABLE super.man (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA duper;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE SCHEMA duper;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'duper',\n p_relname := 'man_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE duper.man(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE TABLE duper.man(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'duper',\n p_relname := 'man_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE duper.man (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE TABLE duper.man (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'super',\n p_relname := 'man',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE super.man ADD COLUMN foo text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n ALTER TABLE super.man ADD COLUMN foo text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'duper',\n p_relname := 'man',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE duper.man ADD COLUMN foo text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n ALTER TABLE duper.man ADD COLUMN foo text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE super.man CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n DROP TABLE super.man CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE duper.man;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n DROP TABLE duper.man;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
-(432 rows)
+(416 rows)
DO $$
DECLARE v_ct INT;
diff --git a/expected/25_1_5_features.out b/expected/25_1_5_features.out
index 22120c2..d25cf5f 100644
--- a/expected/25_1_5_features.out
+++ b/expected/25_1_5_features.out
@@ -17,9 +17,9 @@ SET search_path TO public;
SET ROLE test_pgl_ddl_deploy;
CREATE TABLE foo(id serial primary key, bla int);
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------------------+---------------------------------------------------
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------------------+----------------------------------------------------
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int);
(1 row)
GRANT SELECT ON foo TO PUBLIC;
@@ -27,10 +27,10 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.include_everything
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | include_everything
-----------+---------------------------------------------------+---------------------------------------------------+--------------------
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
+ set_name | ddl_sql_raw | ddl_sql_sent | include_everything
+----------+---------------------------------------------------+----------------------------------------------------+--------------------
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
(2 rows)
INSERT INTO foo (bla) VALUES (1),(2),(3);
@@ -40,12 +40,12 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.include_everything
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | include_everything
-----------+---------------------------------------------------+---------------------------------------------------+--------------------
- test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC; | t
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
+ set_name | ddl_sql_raw | ddl_sql_sent | include_everything
+----------+---------------------------------------------------+----------------------------------------------------+--------------------
+ test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public; | t
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
(4 rows)
SELECT * FROM pgl_ddl_deploy.unhandled;
@@ -73,13 +73,13 @@ SELECT pgl_ddl_deploy.deploy(id) FROM pgl_ddl_deploy.set_configs WHERE set_name
SET ROLE test_pgl_ddl_deploy;
CREATE TABLE foo(id serial primary key, bla int);
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------------------+---------------------------------------------------
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------------------+----------------------------------------------------
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int);
test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC;
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC;
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int);
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public;
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public;
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int);
(5 rows)
GRANT SELECT ON foo TO PUBLIC;
@@ -87,14 +87,14 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.include_everything
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | include_everything
-----------+---------------------------------------------------+---------------------------------------------------+--------------------
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
- test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC; | t
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
+ set_name | ddl_sql_raw | ddl_sql_sent | include_everything
+----------+---------------------------------------------------+----------------------------------------------------+--------------------
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
+ test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public; | t
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
(6 rows)
INSERT INTO foo (bla) VALUES (1),(2),(3);
@@ -104,16 +104,16 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.include_everything
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | include_everything
-----------+---------------------------------------------------+---------------------------------------------------+--------------------
- test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC; | t
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
- test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC; | t
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
+ set_name | ddl_sql_raw | ddl_sql_sent | include_everything
+----------+---------------------------------------------------+----------------------------------------------------+--------------------
+ test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public; | t
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
+ test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public; | t
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
(8 rows)
SELECT * FROM pgl_ddl_deploy.unhandled;
diff --git a/expected/33_allowed.out b/expected/33_allowed.out
index 2d9f4ea..ebe4f19 100644
--- a/expected/33_allowed.out
+++ b/expected/33_allowed.out
@@ -14,73 +14,73 @@ SELECT * FROM check_rep_tables();
(4 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test2 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test1 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test2 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test1 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
(4 rows)
ALTER TABLE foo ADD COLUMN bla TEXT;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test2 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test1 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test2 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test1 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
(8 rows)
INSERT INTO foo (bla) VALUES (1),(2),(3);
DROP TABLE foo CASCADE;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test2 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
(10 rows)
CREATE FUNCTION foo() RETURNS INT AS
@@ -89,64 +89,64 @@ SELECT 1;
$BODY$
LANGUAGE SQL STABLE;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+--------------------------------------+--------------------------------------
- test4 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test3 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test2 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test1 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+--------------------------------------+-----------------------------------------
+ test4 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test3 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test2 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test1 | CREATE FUNCTION foo() RETURNS INT AS+| CREATE FUNCTION foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test2 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
(10 rows)
ALTER FUNCTION foo() OWNER TO current_user;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
set_name | ddl_sql_raw | ddl_sql_sent
----------+---------------------------------------------+---------------------------------------------
- test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test2 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test1 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test4 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test3 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test2 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test1 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test2 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test1 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test4 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test3 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test2 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test1 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
(10 rows)
@@ -159,20 +159,20 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test2 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test1 | DROP FUNCTION foo(); | DROP FUNCTION foo();
- test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test2 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test1 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test4 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test3 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test2 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test1 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test4 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test3 | CREATE FUNCTION foo() RETURNS INT AS +| CREATE FUNCTION foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
(10 rows)
CREATE VIEW fooview AS
@@ -180,46 +180,46 @@ SELECT 1 AS myfield;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
set_name | ddl_sql_raw | ddl_sql_sent
----------+---------------------------------------------+---------------------------------------------
- test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test2 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test1 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test2 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test1 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
test4 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test3 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test2 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test1 | DROP FUNCTION foo(); | DROP FUNCTION foo();
- test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
- test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO current_user;
+ test4 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
+ test3 | ALTER FUNCTION foo() OWNER TO current_user; | ALTER FUNCTION foo() OWNER TO CURRENT_USER;
(10 rows)
ALTER VIEW fooview RENAME TO barview;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------+---------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------+---------------------------------------------
test4 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test3 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test2 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test1 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
- test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test2 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test1 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test2 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test1 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
test4 | DROP FUNCTION foo(); | DROP FUNCTION foo();
test3 | DROP FUNCTION foo(); | DROP FUNCTION foo();
(10 rows)
DROP VIEW barview;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------+---------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------+---------------------------------------------
test4 | DROP VIEW barview; | DROP VIEW barview;
test3 | DROP VIEW barview; | DROP VIEW barview;
test2 | DROP VIEW barview; | DROP VIEW barview;
@@ -228,10 +228,10 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test2 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
test1 | ALTER VIEW fooview RENAME TO barview; | ALTER VIEW fooview RENAME TO barview;
- test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ test4 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test3 | CREATE VIEW fooview AS +| CREATE VIEW fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
(10 rows)
CREATE SEQUENCE foo;
@@ -313,34 +313,34 @@ SELECT * FROM check_rep_tables();
(8 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------+-------------------------------------------------
- test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test6 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test5 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test4 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test3 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test2 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test1 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------+--------------------------------------------------
+ test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test6 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test5 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test4 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test3 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test2 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test1 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
(10 rows)
ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------+-------------------------------------------------
- test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test6 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test5 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test4 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------+--------------------------------------------------
+ test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test6 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test5 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test4 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
(10 rows)
INSERT INTO foobar.foo (bla) VALUES (1),(2),(3);
@@ -356,8 +356,8 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test2 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test1 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
- test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
+ test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
(10 rows)
CREATE FUNCTION foobar.foo() RETURNS INT AS
@@ -366,48 +366,48 @@ SELECT 1;
$BODY$
LANGUAGE SQL STABLE;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------------+---------------------------------------------
- test8 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test7 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test6 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test5 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test4 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test3 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test2 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test1 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS INT AS+
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------------+------------------------------------------------
+ test8 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test7 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test6 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test5 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test4 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test3 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test2 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test1 | CREATE FUNCTION foobar.foo() RETURNS INT AS+| CREATE FUNCTION foobar.foo() RETURNS int AS $$+
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
test8 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test7 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
(10 rows)
@@ -416,24 +416,24 @@ ALTER FUNCTION foobar.foo() OWNER TO current_user;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
set_name | ddl_sql_raw | ddl_sql_sent
----------+----------------------------------------------------+----------------------------------------------------
- test8 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test7 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test6 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test5 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test4 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test3 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test2 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test1 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test8 | CREATE FUNCTION foobar.foo() RETURNS INT AS +| CREATE FUNCTION foobar.foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
- test7 | CREATE FUNCTION foobar.foo() RETURNS INT AS +| CREATE FUNCTION foobar.foo() RETURNS INT AS +
- | $BODY$ +| $BODY$ +
- | SELECT 1; +| SELECT 1; +
- | $BODY$ +| $BODY$ +
- | LANGUAGE SQL STABLE; | LANGUAGE SQL STABLE;
+ test8 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test7 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test6 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test5 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test4 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test3 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test2 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test1 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test8 | CREATE FUNCTION foobar.foo() RETURNS INT AS +| CREATE FUNCTION foobar.foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
+ test7 | CREATE FUNCTION foobar.foo() RETURNS INT AS +| CREATE FUNCTION foobar.foo() RETURNS int AS $$ +
+ | $BODY$ +| SELECT 1; +
+ | SELECT 1; +| $$ LANGUAGE sql STABLE;
+ | $BODY$ +|
+ | LANGUAGE SQL STABLE; |
(10 rows)
DROP FUNCTION foobar.foo();
@@ -448,39 +448,39 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
test2 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
test1 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
- test8 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
- test7 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO current_user;
+ test8 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
+ test7 | ALTER FUNCTION foobar.foo() OWNER TO current_user; | ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;
(10 rows)
CREATE VIEW foobar.fooview AS
SELECT 1 AS myfield;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------+-------------------------------
- test8 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test7 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test6 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test5 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test4 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test3 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test2 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test1 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS+
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------+----------------------------------------------------
+ test8 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test7 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test6 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test5 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test4 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test3 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test2 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test1 | CREATE VIEW foobar.fooview AS+| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
test8 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
test7 | DROP FUNCTION foobar.foo(); | DROP FUNCTION foobar.foo();
(10 rows)
ALTER VIEW foobar.fooview RENAME TO barview;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+----------------------------------------------+----------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+----------------------------------------------+----------------------------------------------------
test8 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
test7 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
test6 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
@@ -489,10 +489,10 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
test2 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
test1 | ALTER VIEW foobar.fooview RENAME TO barview; | ALTER VIEW foobar.fooview RENAME TO barview;
- test8 | CREATE VIEW foobar.fooview AS +| CREATE VIEW foobar.fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
- test7 | CREATE VIEW foobar.fooview AS +| CREATE VIEW foobar.fooview AS +
- | SELECT 1 AS myfield; | SELECT 1 AS myfield;
+ test8 | CREATE VIEW foobar.fooview AS +| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
+ test7 | CREATE VIEW foobar.fooview AS +| CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;
+ | SELECT 1 AS myfield; |
(10 rows)
DROP VIEW foobar.barview;
@@ -566,18 +566,18 @@ SELECT * FROM check_rep_tables();
(0 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------+-----------------------------
- test8 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test7 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test6 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test5 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test4 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test3 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test2 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test1 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test8 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
- test7 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------+------------------------------------
+ test8 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test7 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test6 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test5 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test4 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test3 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test2 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test1 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test8 | ALTER SEQUENCE foobar.foo RESTART; | ALTER SEQUENCE foobar.foo RESTART;
+ test7 | ALTER SEQUENCE foobar.foo RESTART; | ALTER SEQUENCE foobar.foo RESTART;
(10 rows)
SELECT * FROM pgl_ddl_deploy.unhandled;
diff --git a/expected/34_multi.out b/expected/34_multi.out
index ffc6786..2065aa5 100644
--- a/expected/34_multi.out
+++ b/expected/34_multi.out
@@ -19,18 +19,18 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------+-----------------------------
- test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test5 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test4 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test3 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test2 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test1 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test8 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test7 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------+---------------------------
+ test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test5 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test4 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test3 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test2 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test1 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test8 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test7 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
(10 rows)
SELECT set_name, ddl_sql_raw, command_tag, reason FROM pgl_ddl_deploy.unhandled ORDER BY id DESC LIMIT 10;
@@ -60,14 +60,14 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
COMMIT
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------------------+------------------------------------------------
- test7 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test5 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test3 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test1 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test3 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo(id int primary key);
- test1 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo(id int primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------------------+-----------------------------------------------
+ test7 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test5 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test1 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo (id int PRIMARY KEY);
+ test1 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo (id int PRIMARY KEY);
test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
@@ -106,14 +106,14 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------------------------------------------------------+-----------------------------------------------------------------------------
- test7 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test5 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test3 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test1 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test3 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;
- test1 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-----------------------------------------------------------------------------+------------------------------------------------------------------------------
+ test7 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test5 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test3 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test1 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test3 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;
+ test1 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;
test8 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test7 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test6 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
@@ -147,18 +147,18 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+----------------------------------------------+----------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+----------------------------------------------+-----------------------------------------------
test4 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test3 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test2 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test1 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
- test8 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test7 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test6 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test5 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test4 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test3 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
+ test8 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test6 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test5 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test4 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
(10 rows)
SELECT set_name, ddl_sql_raw, command_tag, reason FROM pgl_ddl_deploy.unhandled ORDER BY id DESC LIMIT 10;
diff --git a/expected/34_multi_1.out b/expected/34_multi_1.out
index 7f4c9f5..a9254db 100644
--- a/expected/34_multi_1.out
+++ b/expected/34_multi_1.out
@@ -23,18 +23,18 @@ CREATE TABLE
INSERT 0 3
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------+-----------------------------
- test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test5 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test4 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test3 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test2 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test1 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
- test8 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
- test7 | DROP SCHEMA foobar CASCADE; | DROP SCHEMA foobar CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------+---------------------------
+ test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test5 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test4 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test3 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test2 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test1 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
+ test8 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
+ test7 | DROP SEQUENCE foobar.foo; | DROP SEQUENCE foobar.foo;
(10 rows)
SELECT set_name, ddl_sql_raw, command_tag, reason FROM pgl_ddl_deploy.unhandled ORDER BY id DESC LIMIT 10;
@@ -68,14 +68,14 @@ BEGIN
CREATE TABLE
COMMIT
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------------------+------------------------------------------------
- test7 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test5 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test3 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test1 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo(id int primary key);
- test3 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo(id int primary key);
- test1 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo(id int primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------------------+-----------------------------------------------
+ test7 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test5 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test1 | BEGIN; CREATE TABLE foobar.foo(id int primary key); COMMIT; | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo (id int PRIMARY KEY);
+ test1 | BEGIN; CREATE TABLE foo(id int primary key); COMMIT; | CREATE TABLE foo (id int PRIMARY KEY);
test8 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test7 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
test6 | CREATE SCHEMA foobar; | CREATE SCHEMA foobar;
@@ -116,14 +116,14 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
CREATE TABLE
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-----------------------------------------------------------------------------+-----------------------------------------------------------------------------
- test7 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test5 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test3 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test1 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;
- test3 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;
- test1 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-----------------------------------------------------------------------------+------------------------------------------------------------------------------
+ test7 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test5 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test3 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test1 | CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE; | CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;
+ test3 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;
+ test1 | CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE; | CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;
test8 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test7 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test6 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
@@ -157,18 +157,18 @@ WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
WARNING: Unhandled deployment logged in pgl_ddl_deploy.unhandled
DROP TABLE
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+----------------------------------------------+----------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+----------------------------------------------+-----------------------------------------------
test4 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test3 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test2 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
test1 | DROP TABLE foo, foobar.foo CASCADE; | DROP TABLE foo, foobar.foo CASCADE;
- test8 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test7 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test6 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test5 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test4 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
- test3 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo(id int primary key);
+ test8 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test6 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test5 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test4 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
+ test3 | CREATE TABLE foobar.foo(id int primary key); | CREATE TABLE foobar.foo (id int PRIMARY KEY);
(10 rows)
SELECT set_name, ddl_sql_raw, command_tag, reason FROM pgl_ddl_deploy.unhandled ORDER BY id DESC LIMIT 10;
diff --git a/expected/35_edges.out b/expected/35_edges.out
index 14a7b1f..f33dc69 100644
--- a/expected/35_edges.out
+++ b/expected/35_edges.out
@@ -5,18 +5,18 @@ CREATE TABLE foo (id SERIAL PRIMARY KEY);
--This is an edge case that currently can't be dealt with well with filtered replication.
ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------------------------------+------------------------------------------------------------------
- test8 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test7 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test6 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test5 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test4 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test3 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test2 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test1 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);
- test4 | CREATE TABLE foo (id SERIAL PRIMARY KEY); | CREATE TABLE foo (id SERIAL PRIMARY KEY);
- test3 | CREATE TABLE foo (id SERIAL PRIMARY KEY); | CREATE TABLE foo (id SERIAL PRIMARY KEY);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------------------------------+-------------------------------------------------------------------
+ test8 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test7 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test6 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test5 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test4 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test3 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test2 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test1 | ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id); | ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);
+ test4 | CREATE TABLE foo (id SERIAL PRIMARY KEY); | CREATE TABLE foo (id serial PRIMARY KEY);
+ test3 | CREATE TABLE foo (id SERIAL PRIMARY KEY); | CREATE TABLE foo (id serial PRIMARY KEY);
(10 rows)
DROP TABLE foobar.foo CASCADE;
diff --git a/expected/41_transaction.out b/expected/41_transaction.out
index c66b9ec..d1f4d78 100644
--- a/expected/41_transaction.out
+++ b/expected/41_transaction.out
@@ -15,24 +15,24 @@ SELECT * FROM check_rep_tables();
(4 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test2 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test1 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test2 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test1 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
test8 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
test7 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
test6 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
@@ -43,28 +43,28 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
ALTER TABLE foo ADD COLUMN bla TEXT;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test2 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test1 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test2 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test1 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
test8 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
test7 | DROP TABLE foobar.foo; | DROP TABLE foobar.foo;
(10 rows)
@@ -72,24 +72,24 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
INSERT INTO foo (bla) VALUES (1),(2),(3);
DROP TABLE foo CASCADE;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+------------------------------------------+------------------------------------------
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+------------------------------------------+-------------------------------------------
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test2 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
- test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla TEXT;
- test4 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
- test3 | /*** +| /*** +
- | In default schema +| In default schema +
- | **/ +| **/ +
- | CREATE TABLE foo(id serial primary key); | CREATE TABLE foo(id serial primary key);
+ test4 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foo ADD COLUMN bla TEXT; | ALTER TABLE foo ADD COLUMN bla text;
+ test4 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
+ test3 | /*** +| CREATE TABLE foo (id serial PRIMARY KEY);
+ | In default schema +|
+ | **/ +|
+ | CREATE TABLE foo(id serial primary key); |
(10 rows)
CREATE TABLE foobar.foo(id serial primary key);
@@ -107,34 +107,34 @@ SELECT * FROM check_rep_tables();
(8 rows)
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------+-------------------------------------------------
- test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test6 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test5 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test4 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test3 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test2 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test1 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------+--------------------------------------------------
+ test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test6 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test5 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test4 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test3 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test2 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test1 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
test4 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
test3 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
(10 rows)
ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+-------------------------------------------------+-------------------------------------------------
- test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test6 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test5 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test4 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test3 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test2 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test1 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
- test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo(id serial primary key);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------+--------------------------------------------------
+ test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test6 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test5 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test4 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test3 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test2 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test1 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test8 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
+ test7 | CREATE TABLE foobar.foo(id serial primary key); | CREATE TABLE foobar.foo (id serial PRIMARY KEY);
(10 rows)
INSERT INTO foobar.foo (bla) VALUES (1),(2),(3);
@@ -150,8 +150,8 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test2 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
test1 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
- test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
- test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla TEXT;
+ test8 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
+ test7 | ALTER TABLE foobar.foo ADD COLUMN bla TEXT; | ALTER TABLE foobar.foo ADD COLUMN bla text;
(10 rows)
COMMIT;
diff --git a/expected/43_new_set_behavior.out b/expected/43_new_set_behavior.out
index cb8466a..e2e90cf 100644
--- a/expected/43_new_set_behavior.out
+++ b/expected/43_new_set_behavior.out
@@ -75,9 +75,9 @@ BEGIN;
INSERT INTO pgl_ddl_deploy.set_configs (set_name, include_only_repset_tables)
VALUES ('temp_1', TRUE);
SELECT create_tags, drop_tags FROM pgl_ddl_deploy.set_configs WHERE set_name = 'temp_1';
- create_tags | drop_tags
------------------+-----------
- {"ALTER TABLE"} |
+ create_tags | drop_tags
+-------------------------+-----------
+ {"ALTER TABLE",COMMENT} |
(1 row)
ROLLBACK;
diff --git a/expected/44_multi_set_tags.out b/expected/44_multi_set_tags.out
index 044236e..11fbe8f 100644
--- a/expected/44_multi_set_tags.out
+++ b/expected/44_multi_set_tags.out
@@ -11,11 +11,11 @@ FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
WHERE c.set_name = 'test1'
ORDER BY e.id DESC LIMIT 4;
- create_tags | set_name | ddl_sql_raw | ddl_sql_sent
---------------------------------------------------------------------------------------------------------------+----------+----------------------------------------------+----------------------------------------------
- {"CREATE VIEW","ALTER VIEW","CREATE FUNCTION","ALTER FUNCTION"} | test1 | CREATE VIEW viewer.vw_foo AS +| CREATE VIEW viewer.vw_foo AS +
- | | SELECT * FROM viewer.foo; | SELECT * FROM viewer.foo;
- {"ALTER TABLE","CREATE SEQUENCE","ALTER SEQUENCE","CREATE SCHEMA","CREATE TABLE","CREATE TYPE","ALTER TYPE"} | test1 | CREATE TABLE viewer.foo(id int primary key); | CREATE TABLE viewer.foo(id int primary key);
+ create_tags | set_name | ddl_sql_raw | ddl_sql_sent
+--------------------------------------------------------------------------------------------------------------+----------+----------------------------------------------+--------------------------------------------------------
+ {"CREATE VIEW","ALTER VIEW","CREATE FUNCTION","ALTER FUNCTION"} | test1 | CREATE VIEW viewer.vw_foo AS +| CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;
+ | | SELECT * FROM viewer.foo; |
+ {"ALTER TABLE","CREATE SEQUENCE","ALTER SEQUENCE","CREATE SCHEMA","CREATE TABLE","CREATE TYPE","ALTER TYPE"} | test1 | CREATE TABLE viewer.foo(id int primary key); | CREATE TABLE viewer.foo (id int PRIMARY KEY);
{"ALTER TABLE","CREATE SEQUENCE","ALTER SEQUENCE","CREATE SCHEMA","CREATE TABLE","CREATE TYPE","ALTER TYPE"} | test1 | CREATE SCHEMA viewer; | CREATE SCHEMA viewer;
{"ALTER TABLE","CREATE SEQUENCE","ALTER SEQUENCE","CREATE SCHEMA","CREATE TABLE","CREATE TYPE","ALTER TYPE"} | test1 | DROP TABLE foobar.foo CASCADE; | DROP TABLE foobar.foo CASCADE;
(4 rows)
@@ -28,13 +28,13 @@ FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
WHERE c.set_name = 'test1'
ORDER BY e.id DESC LIMIT 4;
- drop_tags | set_name | ddl_sql_raw | ddl_sql_sent
-----------------------------------------------------------+----------+--------------------------------+--------------------------------
- {"DROP SCHEMA","DROP TABLE","DROP TYPE","DROP SEQUENCE"} | test1 | DROP SCHEMA viewer; | DROP SCHEMA viewer;
- {"DROP SCHEMA","DROP TABLE","DROP TYPE","DROP SEQUENCE"} | test1 | DROP TABLE viewer.foo CASCADE; | DROP TABLE viewer.foo CASCADE;
- {"DROP VIEW","DROP FUNCTION"} | test1 | DROP VIEW viewer.vw_foo; | DROP VIEW viewer.vw_foo;
- {"DROP VIEW","DROP FUNCTION"} | test1 | CREATE VIEW viewer.vw_foo AS +| CREATE VIEW viewer.vw_foo AS +
- | | SELECT * FROM viewer.foo; | SELECT * FROM viewer.foo;
+ drop_tags | set_name | ddl_sql_raw | ddl_sql_sent
+----------------------------------------------------------+----------+----------------------------------------------+--------------------------------------------------------
+ {"DROP SCHEMA","DROP TABLE","DROP TYPE","DROP SEQUENCE"} | test1 | DROP TABLE viewer.foo CASCADE; | DROP TABLE viewer.foo CASCADE;
+ {"DROP VIEW","DROP FUNCTION"} | test1 | DROP VIEW viewer.vw_foo; | DROP VIEW viewer.vw_foo;
+ {"DROP VIEW","DROP FUNCTION"} | test1 | CREATE VIEW viewer.vw_foo AS +| CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;
+ | | SELECT * FROM viewer.foo; |
+ {"DROP SCHEMA","DROP TABLE","DROP TYPE","DROP SEQUENCE"} | test1 | CREATE TABLE viewer.foo(id int primary key); | CREATE TABLE viewer.foo (id int PRIMARY KEY);
(4 rows)
SELECT * FROM pgl_ddl_deploy.exceptions;
diff --git a/expected/47_include_only_repset_tables_3.out b/expected/47_include_only_repset_tables_3.out
index e49e53c..0a53398 100644
--- a/expected/47_include_only_repset_tables_3.out
+++ b/expected/47_include_only_repset_tables_3.out
@@ -9,8 +9,8 @@ WHERE c.set_name LIKE 'my_special_tables%'
ORDER BY e.id DESC LIMIT 10;
create_tags | set_name | ddl_sql_raw | ddl_sql_sent
-----------------+---------------------+--------------------------------------------------+--------------------------------------------------
- {"ALTER TABLE"} | my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier TEXT;
- {"ALTER TABLE"} | my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy TEXT;
+ {"ALTER TABLE"} | my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier text;
+ {"ALTER TABLE"} | my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy text;
(2 rows)
--Test renaming which was missing in 1.2
@@ -34,8 +34,8 @@ WHERE c.set_name LIKE 'my_special_tables%' ORDER BY e.id DESC LIMIT 20;
my_special_tables_2 | ALTER TABLE special.bar RENAME COLUMN happier TO happierz; | ALTER TABLE special.bar RENAME COLUMN happier TO happierz;
my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN id TO id_2; | ALTER TABLE special.foo RENAME COLUMN id TO id_2;
my_special_tables_1 | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true); | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);
- my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy to happyz;
- my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier TEXT;
- my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy TEXT;
+ my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy TO happyz;
+ my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier text;
+ my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy text;
(9 rows)
diff --git a/expected/48_include_only_repset_tables_4.out b/expected/48_include_only_repset_tables_4.out
index a68836e..c54ca57 100644
--- a/expected/48_include_only_repset_tables_4.out
+++ b/expected/48_include_only_repset_tables_4.out
@@ -20,9 +20,9 @@ WHERE c.set_name LIKE 'my_special_tables%' ORDER BY e.id DESC LIMIT 10;
my_special_tables_2 | ALTER TABLE special.bar RENAME COLUMN happier TO happierz; | ALTER TABLE special.bar RENAME COLUMN happier TO happierz;
my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN id TO id_2; | ALTER TABLE special.foo RENAME COLUMN id TO id_2;
my_special_tables_1 | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true); | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);
- my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy to happyz;
- my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier TEXT;
- my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy TEXT;
+ my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy TO happyz;
+ my_special_tables_2 | ALTER TABLE special.bar ADD COLUMN happier TEXT; | ALTER TABLE special.bar ADD COLUMN happier text;
+ my_special_tables_1 | ALTER TABLE special.foo ADD COLUMN happy TEXT; | ALTER TABLE special.foo ADD COLUMN happy text;
(10 rows)
-- Test new subcommand functionality
@@ -56,8 +56,8 @@ INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
WHERE c.set_name LIKE 'my_special_tables%' ORDER BY e.id DESC LIMIT 10;
set_name | ddl_sql_raw | ddl_sql_sent
---------------------+--------------------------------------------------------------------------------+--------------------------------------------------------------------------------
- my_special_tables_1 | ALTER TABLE special.fooz ADD COLUMN bar_id INT; | ALTER TABLE special.fooz ADD COLUMN bar_id INT;
- my_special_tables_2 | ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2); | ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);
+ my_special_tables_1 | ALTER TABLE special.fooz ADD COLUMN bar_id INT; | ALTER TABLE special.fooz ADD COLUMN bar_id int;
+ my_special_tables_2 | ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2); | ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);
my_special_tables_1 | ALTER TABLE special.fooz DISABLE TRIGGER noop; | ALTER TABLE special.fooz DISABLE TRIGGER noop;
my_special_tables_2 | ALTER TABLE special.bar RENAME TO barz; | ALTER TABLE special.bar RENAME TO barz;
my_special_tables_1 | ALTER TABLE special.foo RENAME TO fooz; | ALTER TABLE special.foo RENAME TO fooz;
@@ -65,7 +65,7 @@ WHERE c.set_name LIKE 'my_special_tables%' ORDER BY e.id DESC LIMIT 10;
my_special_tables_2 | ALTER TABLE special.bar RENAME COLUMN happier TO happierz; | ALTER TABLE special.bar RENAME COLUMN happier TO happierz;
my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN id TO id_2; | ALTER TABLE special.foo RENAME COLUMN id TO id_2;
my_special_tables_1 | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true); | ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);
- my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy to happyz;
+ my_special_tables_1 | ALTER TABLE special.foo RENAME COLUMN happy to happyz; | ALTER TABLE special.foo RENAME COLUMN happy TO happyz;
(10 rows)
SET client_min_messages = warning;
diff --git a/expected/48_include_only_repset_tables_4_1.out b/expected/48_include_only_repset_tables_4_1.out
index 44f58f0..a68836e 100644
--- a/expected/48_include_only_repset_tables_4_1.out
+++ b/expected/48_include_only_repset_tables_4_1.out
@@ -45,11 +45,11 @@ LOG: Not processing DDL due to excluded subcommand(s): ENABLE TRIGGER: ALTER TA
-- This contains a tag we want to ignore but we can't separate out the parts - see the warning message
ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);
WARNING: Filtering out more than one subcommand in one ALTER TABLE is not supported.
- Allowing to proceed: Rejected: ADD CONSTRAINT (and recurse), SQL: ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);
+ Allowing to proceed: Rejected: ADD CONSTRAINT, SQL: ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);
ALTER TABLE special.fooz ADD COLUMN bar_id INT;
-- This one should be ignored as well
ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
-LOG: Not processing DDL due to excluded subcommand(s): ADD CONSTRAINT (and recurse): ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
+LOG: Not processing DDL due to excluded subcommand(s): ADD CONSTRAINT: ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
SELECT c.set_name, ddl_sql_raw, ddl_sql_sent
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
diff --git a/expected/50_is_deployed.out b/expected/50_is_deployed.out
index 7a6f736..c4df3f6 100644
--- a/expected/50_is_deployed.out
+++ b/expected/50_is_deployed.out
@@ -52,18 +52,18 @@ SELECT set_name, is_deployed FROM pgl_ddl_deploy.event_trigger_schema ORDER BY i
CREATE TABLE foobar (id serial primary key);
DROP TABLE foobar;
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+----------------------------------+----------------------------------
- test4 | DROP SCHEMA special; | DROP SCHEMA special;
- test3 | DROP SCHEMA special; | DROP SCHEMA special;
- test2 | DROP SCHEMA special; | DROP SCHEMA special;
- test1 | DROP SCHEMA special; | DROP SCHEMA special;
- test4 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
- test3 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
- test2 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
- test1 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
- test4 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
- test3 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+-------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------
+ test4 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test3 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test2 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test1 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test4 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ test3 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ test2 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ test1 | DROP TABLE special.fooz CASCADE; | DROP TABLE special.fooz CASCADE;
+ test4 | ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3); | ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
+ test3 | ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3); | ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);
(10 rows)
--Re-deploy and check again what shows as deployed
@@ -108,11 +108,11 @@ SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY i
test3 | DROP TABLE foobar CASCADE; | DROP TABLE foobar CASCADE;
test2 | DROP TABLE foobar CASCADE; | DROP TABLE foobar CASCADE;
test1 | DROP TABLE foobar CASCADE; | DROP TABLE foobar CASCADE;
- test4 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial primary key);
- test3 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial primary key);
- test2 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial primary key);
- test1 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial primary key);
- test4 | DROP SCHEMA special; | DROP SCHEMA special;
- test3 | DROP SCHEMA special; | DROP SCHEMA special;
+ test4 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial PRIMARY KEY);
+ test3 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial PRIMARY KEY);
+ test2 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial PRIMARY KEY);
+ test1 | CREATE TABLE foobar (id serial primary key); | CREATE TABLE foobar (id serial PRIMARY KEY);
+ test4 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
+ test3 | DROP TABLE special.barz CASCADE; | DROP TABLE special.barz CASCADE;
(10 rows)
diff --git a/expected/51_1_4_features.out b/expected/51_1_4_features.out
index 837c2ef..e58aaf6 100644
--- a/expected/51_1_4_features.out
+++ b/expected/51_1_4_features.out
@@ -75,17 +75,17 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.ddl_only_replication
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | ddl_only_replication
----------------+------------------------------------------------+------------------------------------------------+----------------------
- test_ddl_only | DROP TABLE duper.man; | DROP TABLE duper.man; | t
- test_ddl_only | DROP TABLE super.man CASCADE; | DROP TABLE super.man CASCADE; | f
- test_ddl_only | ALTER TABLE duper.man ADD COLUMN foo text; | ALTER TABLE duper.man ADD COLUMN foo text; | t
- test_ddl_only | ALTER TABLE super.man ADD COLUMN foo text; | ALTER TABLE super.man ADD COLUMN foo text; | f
- test_ddl_only | CREATE TABLE duper.man(id serial primary key); | CREATE TABLE duper.man(id serial primary key); | t
- test_ddl_only | CREATE SCHEMA duper; | CREATE SCHEMA duper; | t
- test_ddl_only | CREATE TABLE super.man(id serial primary key); | CREATE TABLE super.man(id serial primary key); | f
- test_ddl_only | CREATE SCHEMA super; | CREATE SCHEMA super; | f
- test4 | CREATE SCHEMA bla; | CREATE SCHEMA bla; | f
- test3 | CREATE SCHEMA bla; | CREATE SCHEMA bla; | f
+ set_name | ddl_sql_raw | ddl_sql_sent | ddl_only_replication
+---------------+------------------------------------------------+-------------------------------------------------+----------------------
+ test_ddl_only | DROP TABLE duper.man; | DROP TABLE duper.man; | t
+ test_ddl_only | DROP TABLE super.man CASCADE; | DROP TABLE super.man CASCADE; | f
+ test_ddl_only | ALTER TABLE duper.man ADD COLUMN foo text; | ALTER TABLE duper.man ADD COLUMN foo text; | t
+ test_ddl_only | ALTER TABLE super.man ADD COLUMN foo text; | ALTER TABLE super.man ADD COLUMN foo text; | f
+ test_ddl_only | CREATE TABLE duper.man(id serial primary key); | CREATE TABLE duper.man (id serial PRIMARY KEY); | t
+ test_ddl_only | CREATE SCHEMA duper; | CREATE SCHEMA duper; | t
+ test_ddl_only | CREATE TABLE super.man(id serial primary key); | CREATE TABLE super.man (id serial PRIMARY KEY); | f
+ test_ddl_only | CREATE SCHEMA super; | CREATE SCHEMA super; | f
+ test4 | CREATE SCHEMA bla; | CREATE SCHEMA bla; | f
+ test3 | CREATE SCHEMA bla; | CREATE SCHEMA bla; | f
(10 rows)
diff --git a/expected/52_sub_retries.out b/expected/52_sub_retries.out
index c6c9a16..8f002a5 100644
--- a/expected/52_sub_retries.out
+++ b/expected/52_sub_retries.out
@@ -2,36 +2,36 @@
--If adding new tests, it is best to keep this file as the last test before cleanup.
SET client_min_messages = warning;
SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(message::text, 'p_pid := (\d+)', 'p_pid := ?'), 'p_provider_name := (NULL|''\w+'')', 'p_provider_name := ?'), 'p_driver := (''\w+'')', 'p_driver := ?') as message FROM all_queues() WHERE NOT message::text LIKE '%notify_subscription_refresh%' ORDER BY queued_at;
- pubnames | message_type | message
------------------------+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n /***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n /***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ pubnames | message_type | message
+-----------------------+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER VIEW fooview RENAME TO barview;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER VIEW fooview RENAME TO barview;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER VIEW fooview RENAME TO barview;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -60,22 +60,22 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA foobar;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -84,22 +84,22 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS INT AS\n$BODY$\nSELECT 1;\n$BODY$\nLANGUAGE SQL STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO current_user;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO current_user;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO current_user;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE FUNCTION foobar.foo() RETURNS int AS $$\nSELECT 1;\n$$ LANGUAGE sql STABLE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER FUNCTION foobar.foo() OWNER TO CURRENT_USER;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foobar.foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foobar.foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foobar.foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -108,14 +108,14 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP FUNCTION foobar.foo();$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foobar.foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP FUNCTION foobar.foo();$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP FUNCTION foobar.foo();\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS\nSELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'fooview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW foobar.fooview AS SELECT 1 AS myfield;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW foobar.fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER VIEW foobar.fooview RENAME TO barview;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW foobar.fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER VIEW foobar.fooview RENAME TO barview;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'barview',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER VIEW foobar.fooview RENAME TO barview;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER VIEW foobar.fooview RENAME TO barview;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -156,14 +156,6 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SEQUENCE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SEQUENCE foobar.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SEQUENCE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SEQUENCE foobar.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SEQUENCE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SEQUENCE foobar.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA foobar;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA foobar;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -172,12 +164,12 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA foobar;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA foobar;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA foobar;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ CREATE TABLE foo(id int primary key); $PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo(id int primary key); \n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foobar.foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ CREATE TABLE foobar.foo(id int primary key); $PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foobar.foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key); \n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foobar.foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ CREATE TABLE foobar.foo(id int primary key); $PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ CREATE TABLE foobar.foo(id int primary key); $pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key); \n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -190,48 +182,48 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo(id int primary key); DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key); DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id int PRIMARY KEY); DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY); DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo, foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo, foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo, foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo, foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo, foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo, foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo, foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo, foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id SERIAL PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id SERIAL PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id SERIAL PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id INT REFERENCES foo(id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN foo_id int REFERENCES foo (id);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -256,34 +248,34 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n /***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$/***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n /***\nIn default schema\n**/\nCREATE TABLE foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo(id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar.foo (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar.foo (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test5} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test5'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 5,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test6} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test6'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE foobar.foo ADD COLUMN bla text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 6,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test7} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test7'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 7,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test8} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test8'],\n p_nspname := 'foobar',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE foobar.foo ADD COLUMN bla text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE foobar.foo ADD COLUMN bla text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 8,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -296,14 +288,14 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA viewer;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA viewer;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA viewer;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE viewer.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE viewer.foo(id int primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE viewer.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo(id int primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE viewer.foo(id int primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW viewer.vw_foo AS\nSELECT * FROM viewer.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE viewer.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE viewer.foo (id int PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE viewer.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'viewer',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE viewer.foo (id int PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE viewer.foo (id int PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'viewer',\n p_relname := 'vw_foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE VIEW viewer.vw_foo AS SELECT * FROM viewer.foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP VIEW viewer.vw_foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP VIEW viewer.vw_foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP VIEW viewer.vw_foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP VIEW viewer.vw_foo;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP VIEW viewer.vw_foo;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP VIEW viewer.vw_foo;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -312,46 +304,42 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE viewer.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE viewer.foo CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE viewer.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE viewer.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE viewer.foo CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE viewer.foo CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA viewer;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA viewer;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA viewer;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA viewer;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA viewer;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA special;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE SCHEMA special;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA special;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE SCHEMA special;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.foo (id serial primary key, foo text, bar text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial primary key, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.foo (id serial primary key, foo text, bar text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial primary key, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.bar (id serial primary key, super text, man text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial primary key, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.bar (id serial primary key, super text, man text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial primary key, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.bar (id serial primary key, super text, man text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial primary key, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.bar (id serial primary key, super text, man text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD COLUMN happy TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD COLUMN happy TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_2'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 16,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier TEXT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar ADD COLUMN happier TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier TEXT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar ADD COLUMN happier TEXT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME COLUMN happy to happyz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy to happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME COLUMN happy to happyz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.foo (id serial PRIMARY KEY, foo text, bar text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'bar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD COLUMN happy text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD COLUMN happy text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD COLUMN happy text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD COLUMN happy text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_2'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 16,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar ADD COLUMN happier text;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar ADD COLUMN happier text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'bar',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar ADD COLUMN happier text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar ADD COLUMN happier text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME COLUMN happy TO happyz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN happy TO happyz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME COLUMN happy TO happyz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo ADD CONSTRAINT bla CHECK (true);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME CONSTRAINT bla to blaz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.foo RENAME CONSTRAINT bla TO blaz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'foo',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.foo RENAME COLUMN id TO id_2;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -377,10 +365,10 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar RENAME TO barz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.bar RENAME TO barz;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar RENAME TO barz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar RENAME TO barz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.bar RENAME TO barz;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.bar RENAME TO barz;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE OR REPLACE FUNCTION noop() RETURNS TRIGGER AS $BODY$\nBEGIN\nRETURN NULL;\nEND;\n$BODY$\nLANGUAGE plpgsql;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 11,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE OR REPLACE FUNCTION noop() RETURNS trigger AS $$\nBEGIN\nRETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz DISABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz DISABLE TRIGGER noop;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz DISABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz DISABLE TRIGGER noop;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz DISABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz DISABLE TRIGGER noop;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -390,16 +378,16 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ENABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ENABLE TRIGGER noop;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ENABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ENABLE TRIGGER noop;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ENABLE TRIGGER noop;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ENABLE TRIGGER noop;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 16,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.barz ADD COLUMN foo_id INT REFERENCES special.fooz (id_2);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD COLUMN bar_id INT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id INT;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD COLUMN bar_id INT;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 16,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'barz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.barz ADD COLUMN foo_id int REFERENCES special.fooz (id_2);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {my_special_tables_1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['my_special_tables_1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id int;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 15,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id int;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD COLUMN bar_id int;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD COLUMN bar_id int;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD COLUMN bar_id int;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD COLUMN bar_id int;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'special',\n p_relname := 'fooz',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n ALTER TABLE special.fooz ADD CONSTRAINT coolness FOREIGN KEY (bar_id) REFERENCES special.barz (id_3);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -412,14 +400,10 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE special.barz CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE special.barz CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE special.barz CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE special.barz CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE special.barz CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE special.barz CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA special;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP SCHEMA special;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA special;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP SCHEMA special;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP SCHEMA special;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar (id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar (id serial primary key);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar (id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar (id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$CREATE TABLE foobar (id serial PRIMARY KEY);$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := 'public',\n p_relname := 'foobar_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE foobar (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n CREATE TABLE foobar (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test1} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test1'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 1,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test2} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test2'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$DROP TABLE foobar CASCADE;$PGL_DDL_DEPLOY$);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 2,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE foobar CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO \"$user\", public;\n\n DROP TABLE foobar CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
@@ -429,14 +413,14 @@ SELECT pubnames, message_type, regexp_replace(regexp_replace(regexp_replace(mess
{test3} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test3'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA bla;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE SCHEMA bla;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 3,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test4} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test4'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA bla;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE SCHEMA bla;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 4,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA super;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE SCHEMA super;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'super',\n p_relname := 'man_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE super.man(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE TABLE super.man(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'super',\n p_relname := 'man_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE super.man (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE TABLE super.man (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE SCHEMA duper;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE SCHEMA duper;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
- {test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'duper',\n p_relname := 'man_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE duper.man(id serial primary key);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE TABLE duper.man(id serial primary key);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
+ {test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'duper',\n p_relname := 'man_pkey',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$CREATE TABLE duper.man (id serial PRIMARY KEY);$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n CREATE TABLE duper.man (id serial PRIMARY KEY);\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'super',\n p_relname := 'man',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE super.man ADD COLUMN foo text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n ALTER TABLE super.man ADD COLUMN foo text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := 'duper',\n p_relname := 'man',\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$ALTER TABLE duper.man ADD COLUMN foo text;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n ALTER TABLE duper.man ADD COLUMN foo text;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE super.man CASCADE;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n DROP TABLE super.man CASCADE;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 19,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
{test_ddl_only} | Q | "\n SELECT pgl_ddl_deploy.subscriber_command\n (\n p_provider_name := ?,\n p_set_name := ARRAY['test_ddl_only'],\n p_nspname := NULL,\n p_relname := NULL,\n p_ddl_sql_sent := $pgl_ddl_deploy_sql$DROP TABLE duper.man;$pgl_ddl_deploy_sql$,\n p_full_ddl := $pgl_ddl_deploy_sql$\n --Be sure to use provider's search_path for SQL environment consistency\n SET SEARCH_PATH TO '';\n\n DROP TABLE duper.man;\n ;\n $pgl_ddl_deploy_sql$,\n p_pid := ?,\n p_set_config_id := 20,\n p_queue_subscriber_failures := false,\n p_signal_blocking_subscriber_sessions := NULL,\n p_lock_timeout := 3000,\n p_driver := ?\n );\n "
-(432 rows)
+(416 rows)
DO $$
DECLARE v_ct INT;
diff --git a/expected/53_1_5_features.out b/expected/53_1_5_features.out
index 22120c2..d25cf5f 100644
--- a/expected/53_1_5_features.out
+++ b/expected/53_1_5_features.out
@@ -17,9 +17,9 @@ SET search_path TO public;
SET ROLE test_pgl_ddl_deploy;
CREATE TABLE foo(id serial primary key, bla int);
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------------------+---------------------------------------------------
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------------------+----------------------------------------------------
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int);
(1 row)
GRANT SELECT ON foo TO PUBLIC;
@@ -27,10 +27,10 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.include_everything
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | include_everything
-----------+---------------------------------------------------+---------------------------------------------------+--------------------
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
+ set_name | ddl_sql_raw | ddl_sql_sent | include_everything
+----------+---------------------------------------------------+----------------------------------------------------+--------------------
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
(2 rows)
INSERT INTO foo (bla) VALUES (1),(2),(3);
@@ -40,12 +40,12 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.include_everything
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | include_everything
-----------+---------------------------------------------------+---------------------------------------------------+--------------------
- test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC; | t
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
+ set_name | ddl_sql_raw | ddl_sql_sent | include_everything
+----------+---------------------------------------------------+----------------------------------------------------+--------------------
+ test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public; | t
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
(4 rows)
SELECT * FROM pgl_ddl_deploy.unhandled;
@@ -73,13 +73,13 @@ SELECT pgl_ddl_deploy.deploy(id) FROM pgl_ddl_deploy.set_configs WHERE set_name
SET ROLE test_pgl_ddl_deploy;
CREATE TABLE foo(id serial primary key, bla int);
SELECT set_name, ddl_sql_raw, ddl_sql_sent FROM pgl_ddl_deploy.events ORDER BY id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent
-----------+---------------------------------------------------+---------------------------------------------------
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int);
+ set_name | ddl_sql_raw | ddl_sql_sent
+----------+---------------------------------------------------+----------------------------------------------------
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int);
test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE;
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC;
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC;
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int);
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public;
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public;
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int);
(5 rows)
GRANT SELECT ON foo TO PUBLIC;
@@ -87,14 +87,14 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.include_everything
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | include_everything
-----------+---------------------------------------------------+---------------------------------------------------+--------------------
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
- test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC; | t
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
+ set_name | ddl_sql_raw | ddl_sql_sent | include_everything
+----------+---------------------------------------------------+----------------------------------------------------+--------------------
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
+ test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public; | t
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
(6 rows)
INSERT INTO foo (bla) VALUES (1),(2),(3);
@@ -104,16 +104,16 @@ SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.include_everything
FROM pgl_ddl_deploy.events e
INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
ORDER BY e.id DESC LIMIT 10;
- set_name | ddl_sql_raw | ddl_sql_sent | include_everything
-----------+---------------------------------------------------+---------------------------------------------------+--------------------
- test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC; | t
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
- test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
- test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE INSERT ON foo FROM PUBLIC; | t
- test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT SELECT ON foo TO PUBLIC; | t
- test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo(id serial primary key, bla int); | f
+ set_name | ddl_sql_raw | ddl_sql_sent | include_everything
+----------+---------------------------------------------------+----------------------------------------------------+--------------------
+ test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public; | t
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
+ test1 | DROP TABLE foo CASCADE; | DROP TABLE foo CASCADE; | f
+ test1 | REVOKE INSERT ON foo FROM PUBLIC; | REVOKE insert ON foo FROM public; | t
+ test1 | GRANT SELECT ON foo TO PUBLIC; | GRANT select ON foo TO public; | t
+ test1 | CREATE TABLE foo(id serial primary key, bla int); | CREATE TABLE foo (id serial PRIMARY KEY, bla int); | f
(8 rows)
SELECT * FROM pgl_ddl_deploy.unhandled;
diff --git a/expected/56_1_6_features.out b/expected/56_1_6_features.out
index 2d6fe04..bcc1071 100644
--- a/expected/56_1_6_features.out
+++ b/expected/56_1_6_features.out
@@ -58,14 +58,3 @@ In <= 1.5, returned this:
{"DROP SCHEMA","DROP TABLE","DROP FUNCTION","DROP TYPE","DROP VIEW","DROP SEQUENCE"}
(1 row)
*/
-SET client_min_messages TO warning;
-DROP OWNED BY test_pgl_ddl_deploy;
-DROP ROLE test_pgl_ddl_deploy;
-DROP ROLE unpriv;
-DROP EXTENSION pgl_ddl_deploy CASCADE;
-DROP EXTENSION IF EXISTS pglogical CASCADE;
-DROP SCHEMA IF EXISTS pglogical CASCADE;
-DROP TABLE IF EXISTS tmp_objs;
-DROP SCHEMA IF EXISTS special CASCADE;
-DROP SCHEMA IF EXISTS bla CASCADE;
-DROP SCHEMA IF EXISTS pgl_ddl_deploy CASCADE;
diff --git a/expected/57_2_4_features.out b/expected/57_2_4_features.out
new file mode 100644
index 0000000..7e41ab6
--- /dev/null
+++ b/expected/57_2_4_features.out
@@ -0,0 +1,61 @@
+SET client_min_messages = warning;
+CREATE PUBLICATION test_indexes_yes;
+CREATE PUBLICATION test_indexes_no;
+INSERT INTO pgl_ddl_deploy.set_configs (set_name, include_schema_regex, lock_safe_deployment, allow_multi_statements, include_indexes)
+VALUES ('test_indexes_yes', '^yindex.*', true, true, true);
+INSERT INTO pgl_ddl_deploy.set_configs (set_name, include_schema_regex, lock_safe_deployment, allow_multi_statements, include_indexes)
+VALUES ('test_indexes_no', '^nindex.*', true, true, false);
+SELECT pgl_ddl_deploy.deploy('test_indexes_yes');
+ deploy
+--------
+ t
+(1 row)
+
+SELECT pgl_ddl_deploy.deploy('test_indexes_no');
+ deploy
+--------
+ t
+(1 row)
+
+CREATE SCHEMA yindex;
+CREATE TABLE yindex.widgets(id serial primary key, type varchar);
+CREATE SCHEMA nindex;
+CREATE TABLE nindex.widgets(id serial primary key, type varchar);
+CREATE INDEX yindex_widgets_type_idx ON yindex.widgets(type);
+CREATE INDEX CONCURRENTLY nindex_widgets_type_id_idx ON yindex.widgets(type, id);
+CREATE INDEX nindex_widgets_type_idx ON nindex.widgets(type);
+DROP TABLE yindex.widgets CASCADE;
+DROP TABLE nindex.widgets CASCADE;
+-- We expect to see index events for yindex.widgets but not for nindex.widgets
+SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.ddl_only_replication
+FROM pgl_ddl_deploy.events e
+INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
+ORDER BY e.id DESC LIMIT 10;
+ set_name | ddl_sql_raw | ddl_sql_sent | ddl_only_replication
+------------------+-----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+----------------------
+ test_indexes_no | DROP TABLE nindex.widgets CASCADE; | DROP TABLE nindex.widgets CASCADE; | f
+ test_indexes_yes | DROP TABLE yindex.widgets CASCADE; | DROP TABLE yindex.widgets CASCADE; | f
+ test_indexes_yes | CREATE INDEX CONCURRENTLY nindex_widgets_type_id_idx ON yindex.widgets(type, id); | CREATE INDEX nindex_widgets_type_id_idx ON yindex.widgets USING btree (type, id); | f
+ test_indexes_yes | CREATE INDEX yindex_widgets_type_idx ON yindex.widgets(type); | CREATE INDEX yindex_widgets_type_idx ON yindex.widgets USING btree (type); | f
+ test_indexes_no | CREATE TABLE nindex.widgets(id serial primary key, type varchar); | CREATE TABLE nindex.widgets (id serial PRIMARY KEY, type varchar); | f
+ test_indexes_no | CREATE SCHEMA nindex; | CREATE SCHEMA nindex; | f
+ test_indexes_yes | CREATE TABLE yindex.widgets(id serial primary key, type varchar); | CREATE TABLE yindex.widgets (id serial PRIMARY KEY, type varchar); | f
+ test_indexes_yes | CREATE SCHEMA yindex; | CREATE SCHEMA yindex; | f
+ testspecial | CREATE FUNCTION special.do_replicate_me() +| CREATE FUNCTION special.do_replicate_me() RETURNS int AS $$SELECT 1$$ LANGUAGE sql; | f
+ | RETURNS INT +| |
+ | AS 'SELECT 1' +| |
+ | LANGUAGE SQL; | |
+ testspecial | CREATE TABLE special.bar (id serial primary key, super text, man text); | CREATE TABLE special.bar (id serial PRIMARY KEY, super text, man text); | f
+(10 rows)
+
+SET client_min_messages TO warning;
+DROP OWNED BY test_pgl_ddl_deploy;
+DROP ROLE test_pgl_ddl_deploy;
+DROP ROLE unpriv;
+DROP EXTENSION pgl_ddl_deploy CASCADE;
+DROP EXTENSION IF EXISTS pglogical CASCADE;
+DROP SCHEMA IF EXISTS pglogical CASCADE;
+DROP TABLE IF EXISTS tmp_objs;
+DROP SCHEMA IF EXISTS special CASCADE;
+DROP SCHEMA IF EXISTS bla CASCADE;
+DROP SCHEMA IF EXISTS pgl_ddl_deploy CASCADE;
diff --git a/expected/57_native_features.out b/expected/99_native_features.out
similarity index 100%
rename from expected/57_native_features.out
rename to expected/99_native_features.out
diff --git a/functions/common_exclude_alter_table_subcommands.sql b/functions/common_exclude_alter_table_subcommands.sql
index 2f7f4fd..9507737 100644
--- a/functions/common_exclude_alter_table_subcommands.sql
+++ b/functions/common_exclude_alter_table_subcommands.sql
@@ -3,15 +3,12 @@ RETURNS TEXT[] AS
$BODY$
SELECT ARRAY[
'ADD CONSTRAINT',
- 'ADD CONSTRAINT (and recurse)',
'(re) ADD CONSTRAINT',
'ALTER CONSTRAINT',
'VALIDATE CONSTRAINT',
- 'VALIDATE CONSTRAINT (and recurse)',
'ADD (processed) CONSTRAINT',
'ADD CONSTRAINT (using index)',
'DROP CONSTRAINT',
- 'DROP CONSTRAINT (and recurse)',
'SET LOGGED',
'SET UNLOGGED',
'SET TABLESPACE',
diff --git a/functions/rewrite_transaction_safe.sql b/functions/rewrite_transaction_safe.sql
new file mode 100644
index 0000000..3231ffe
--- /dev/null
+++ b/functions/rewrite_transaction_safe.sql
@@ -0,0 +1,6 @@
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.rewrite_transaction_safe(p_sql text)
+ RETURNS text
+ LANGUAGE c
+ STRICT
+AS '$libdir/pgl_ddl_deploy', $function$rewrite_transaction_safe$function$
+;
\ No newline at end of file
diff --git a/functions/set_tag_defaults.sql b/functions/set_tag_defaults.sql
index 9f271b9..8cf49ac 100644
--- a/functions/set_tag_defaults.sql
+++ b/functions/set_tag_defaults.sql
@@ -5,9 +5,15 @@ AS $function$
BEGIN
IF NEW.create_tags IS NULL THEN
NEW.create_tags = CASE WHEN NEW.include_only_repset_tables THEN pgl_ddl_deploy.standard_repset_only_tags() ELSE pgl_ddl_deploy.standard_create_tags() END;
+ IF NEW.include_indexes AND NOT NEW.include_only_repset_tables THEN
+ NEW.create_tags = NEW.create_tags || '{"CREATE INDEX","ALTER INDEX"}'::TEXT[];
+ END IF;
END IF;
IF NEW.drop_tags IS NULL THEN
NEW.drop_tags = CASE WHEN NEW.include_only_repset_tables THEN NULL ELSE pgl_ddl_deploy.standard_drop_tags() END;
+ IF NEW.include_indexes AND NOT NEW.include_only_repset_tables THEN
+ NEW.drop_tags = NEW.drop_tags || '{"DROP INDEX"}'::TEXT[];
+ END IF;
END IF;
RETURN NEW;
END;
diff --git a/pgl_ddl_deploy--2.3--2.4.sql b/pgl_ddl_deploy--2.3--2.4.sql
new file mode 100644
index 0000000..65fd634
--- /dev/null
+++ b/pgl_ddl_deploy--2.3--2.4.sql
@@ -0,0 +1,786 @@
+/* pgl_ddl_deploy--2.3--2.4.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN include_indexes BOOLEAN NOT NULL DEFAULT FALSE;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.common_exclude_alter_table_subcommands()
+RETURNS TEXT[] AS
+$BODY$
+SELECT ARRAY[
+ 'ADD CONSTRAINT',
+ '(re) ADD CONSTRAINT',
+ 'ALTER CONSTRAINT',
+ 'VALIDATE CONSTRAINT',
+ 'ADD (processed) CONSTRAINT',
+ 'ADD CONSTRAINT (using index)',
+ 'DROP CONSTRAINT',
+ 'SET LOGGED',
+ 'SET UNLOGGED',
+ 'SET TABLESPACE',
+ 'SET RELOPTIONS',
+ 'RESET RELOPTIONS',
+ 'REPLACE RELOPTIONS',
+ 'ENABLE TRIGGER',
+ 'ENABLE TRIGGER (always)',
+ 'ENABLE TRIGGER (replica)',
+ 'DISABLE TRIGGER',
+ 'ENABLE TRIGGER (all)',
+ 'DISABLE TRIGGER (all)',
+ 'ENABLE TRIGGER (user)',
+ 'DISABLE TRIGGER (user)',
+ 'ENABLE RULE',
+ 'ENABLE RULE (always)',
+ 'ENABLE RULE (replica)',
+ 'DISABLE RULE',
+ 'SET OPTIONS']::TEXT[];
+$BODY$
+LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.rewrite_transaction_safe(p_sql text)
+ RETURNS text
+ LANGUAGE c
+ STRICT
+AS '$libdir/pgl_ddl_deploy', $function$rewrite_transaction_safe$function$
+;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.set_tag_defaults()
+ RETURNS trigger
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+IF NEW.create_tags IS NULL THEN
+ NEW.create_tags = CASE WHEN NEW.include_only_repset_tables THEN pgl_ddl_deploy.standard_repset_only_tags() ELSE pgl_ddl_deploy.standard_create_tags() END;
+ IF NEW.include_indexes AND NOT NEW.include_only_repset_tables THEN
+ NEW.create_tags = NEW.create_tags || '{"CREATE INDEX","ALTER INDEX"}'::TEXT[];
+ END IF;
+END IF;
+IF NEW.drop_tags IS NULL THEN
+ NEW.drop_tags = CASE WHEN NEW.include_only_repset_tables THEN NULL ELSE pgl_ddl_deploy.standard_drop_tags() END;
+ IF NEW.include_indexes AND NOT NEW.include_only_repset_tables THEN
+ NEW.drop_tags = NEW.drop_tags || '{"DROP INDEX"}'::TEXT[];
+ END IF;
+END IF;
+RETURN NEW;
+END;
+$function$
+;
+
+CREATE OR REPLACE VIEW pgl_ddl_deploy.event_trigger_schema AS
+WITH vars AS
+(SELECT
+ sc.id,
+ set_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_function_name,
+ 'auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_trigger_name,
+ 'auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_trigger_name,
+ 'auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_trigger_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ create_tags,
+ drop_tags,
+ ddl_only_replication,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ sc.driver,
+
+ /****
+ These constants in DECLARE portion of all functions is identical and can be shared
+ */
+ $BUILD$
+ c_search_path TEXT = (SELECT current_setting('search_path'));
+ c_provider_name TEXT;
+ --TODO: How do I decide which replication set we care about?
+ v_pid INT = pg_backend_pid();
+ v_rec RECORD;
+ v_ddl_sql_raw TEXT;
+ v_ddl_sql_sent TEXT;
+ v_full_ddl TEXT;
+ v_sql_tags TEXT[];
+ v_cmd_rec RECORD;
+ v_subcmd_rec RECORD;
+ v_excluded_subcommands TEXT;
+ v_contains_any_valid_subcommand INT;
+
+ /*****
+ We need to strip the DDL of:
+ 1. Transaction begin and commit, which cannot run inside plpgsql
+ *****/
+ v_txid BIGINT;
+ v_ddl_length INT;
+ v_sql TEXT;
+ v_cmd_count INT;
+ v_match_count INT;
+ v_exclude_always_match_count INT;
+ v_nspname TEXT;
+ v_relname TEXT;
+ v_error TEXT;
+ v_error_detail TEXT;
+ v_context TEXT;
+ v_excluded_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_exception_msg TEXT = 'Deployment exception logged in pgl_ddl_deploy.exceptions';
+
+ --Configurable options in function setup
+ c_set_config_id INT = $BUILD$||sc.id::TEXT||$BUILD$;
+ -- Even though pglogical supports an array of sets, we only pipe DDL through one at a time
+ -- So c_set_name is a text not text[] data type.
+ c_set_name TEXT = '$BUILD$||set_name||$BUILD$';
+ c_driver pgl_ddl_deploy.driver = '$BUILD$||sc.driver||$BUILD$';
+ c_include_schema_regex TEXT = $BUILD$||COALESCE(''''||include_schema_regex||'''','NULL')||$BUILD$;
+ c_lock_safe_deployment BOOLEAN = $BUILD$||lock_safe_deployment||$BUILD$;
+ c_allow_multi_statements BOOLEAN = $BUILD$||allow_multi_statements||$BUILD$;
+ c_include_only_repset_tables BOOLEAN = $BUILD$||include_only_repset_tables||$BUILD$;
+ c_include_everything BOOLEAN = $BUILD$||include_everything||$BUILD$;
+ c_queue_subscriber_failures BOOLEAN = $BUILD$||queue_subscriber_failures||$BUILD$;
+ c_create_tags TEXT[] = '$BUILD$||create_tags::TEXT||$BUILD$';
+ c_blacklisted_tags TEXT[] = '$BUILD$||blacklisted_tags::TEXT||$BUILD$';
+ c_exclude_alter_table_subcommands TEXT[] = $BUILD$||COALESCE(quote_literal(exclude_alter_table_subcommands::TEXT),'NULL')||$BUILD$;
+ c_signal_blocking_subscriber_sessions TEXT = $BUILD$||COALESCE(quote_literal(signal_blocking_subscriber_sessions::TEXT),'NULL')||$BUILD$;
+ c_subscriber_lock_timeout INT = $BUILD$||COALESCE(subscriber_lock_timeout::TEXT,'NULL')||$BUILD$;
+
+ --Constants based on configuration
+ c_exec_prefix TEXT =(CASE
+ WHEN c_lock_safe_deployment
+ THEN 'SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$'
+ ELSE ''
+ END);
+ c_exec_suffix TEXT = (CASE
+ WHEN c_lock_safe_deployment
+ THEN '$PGL_DDL_DEPLOY$);'
+ ELSE ''
+ END);
+ $BUILD$::TEXT AS declare_constants,
+
+ $BUILD$
+ --If there are any matches to our replication config, get the query
+ --This will either be sent, or logged at this point if not deployable
+ IF (c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0 THEN
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+ v_txid = txid_current();
+ END IF;
+ $BUILD$::TEXT AS shared_get_query,
+/****
+ This is the portion of the event trigger function that evaluates if SQL
+ is appropriate to propagate, and does propagate the event. It is shared
+ between the normal and drop event trigger functions.
+ */
+ $BUILD$
+ /****
+ A multi-statement SQL command may fire this event trigger more than once
+ This check ensures the SQL is propagated only once, if at all
+ */
+ IF EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.events
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ OR EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.unhandled
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ THEN
+ RETURN;
+ END IF;
+
+ /****
+ Get the command tags and reject blacklisted tags
+ */
+ v_sql_tags:=(SELECT pgl_ddl_deploy.sql_command_tags(v_ddl_sql_raw));
+ IF (SELECT c_blacklisted_tags && v_sql_tags) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_command_tags',
+ v_txid);
+ RETURN;
+ /****
+ If we are not allowing multi-statements at all, reject
+ */
+ ELSEIF (SELECT ARRAY[TG_TAG]::TEXT[] <> v_sql_tags WHERE NOT c_allow_multi_statements) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_multi_statement',
+ v_txid);
+ RETURN;
+ END IF;
+
+ /****
+ If this is an ALTER TABLE statement and we are excluding any subcommand tags, process now.
+ Note the following.
+
+ Because there can be more than one subcommand, we have a limited ability
+ to filter out subcommands until such a time as we may have a mechanism for rebuilding only
+ the SQL we want. In other words, if we have one subcommand that we DO want (i.e. ADD COLUMN)
+ and one we don't want (i.e. REFERENCES) in the same SQL, and we are "excluding" the latter,
+ we can't do that exclusion safely because we WANT the ADD COLUMN statement. In such a case,
+ we are still going to allow the DDL to go through because it's better to break replication than
+ miss a column addition.
+
+ But if the only subcommand is an excluded one, i.e. ADD CONSTRAINT, then we will indeed ignore
+ the DDL and the function will RETURN without executing replicate_ddl_command.
+ */
+ IF TG_TAG = 'ALTER TABLE' AND c_exclude_alter_table_subcommands IS NOT NULL THEN
+ FOR v_cmd_rec IN
+ SELECT * FROM pg_event_trigger_ddl_commands()
+ LOOP
+ IF pgl_ddl_deploy.get_command_type(v_cmd_rec.command) = 'alter table' THEN
+ WITH subcommands AS (
+ SELECT subcommand,
+ c_exclude_alter_table_subcommands && ARRAY[subcommand] AS subcommand_is_excluded,
+ MAX(CASE WHEN c_exclude_alter_table_subcommands && ARRAY[subcommand] THEN 0 ELSE 1 END) OVER() AS contains_any_valid_subcommand
+ FROM unnest(pgl_ddl_deploy.get_altertable_subcmdinfo(v_cmd_rec.command)) AS subcommand
+ )
+
+ SELECT (SELECT string_agg(subcommand,', ') FROM subcommands WHERE subcommand_is_excluded),
+ (SELECT contains_any_valid_subcommand FROM subcommands LIMIT 1)
+ INTO v_excluded_subcommands,
+ v_contains_any_valid_subcommand;
+ IF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 0 THEN
+ RAISE LOG 'Not processing DDL due to excluded subcommand(s): %: %', v_excluded_subcommands, v_ddl_sql_raw;
+ RETURN;
+ ELSEIF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 1 THEN
+ RAISE WARNING $INNER_BLOCK$Filtering out more than one subcommand in one ALTER TABLE is not supported.
+ Allowing to proceed: Rejected: %, SQL: %$INNER_BLOCK$, v_excluded_subcommands, v_ddl_sql_raw;
+ END IF;
+ END IF;
+ END LOOP;
+ END IF;
+
+ SELECT pgl_ddl_deploy.rewrite_transaction_safe(v_ddl_sql_raw) INTO v_ddl_sql_sent;
+
+ --Get provider name, in order only to run command on a subscriber to this provider
+ c_provider_name:=pgl_ddl_deploy.provider_node_name(c_driver);
+
+ /*
+ Build replication DDL command which will conditionally run only on the subscriber
+ In other words, this MUST be a no-op on the provider
+ **Because the DDL has already run at this point (ddl_command_end)**
+ */
+ v_full_ddl:=$INNER_BLOCK$
+ --Be sure to use provider's search_path for SQL environment consistency
+ SET SEARCH_PATH TO $INNER_BLOCK$||
+ CASE WHEN COALESCE(c_search_path,'') IN('','""') THEN quote_literal('') ELSE c_search_path END||$INNER_BLOCK$;
+
+ $INNER_BLOCK$||c_exec_prefix||v_ddl_sql_sent||c_exec_suffix||$INNER_BLOCK$
+ ;
+ $INNER_BLOCK$;
+ RAISE DEBUG 'v_full_ddl: %', v_full_ddl;
+ RAISE DEBUG 'c_set_config_id: %', c_set_config_id;
+ RAISE DEBUG 'c_set_name: %', c_set_name;
+ RAISE DEBUG 'c_driver: %', c_driver;
+ RAISE DEBUG 'v_ddl_sql_sent: %', v_ddl_sql_sent;
+
+ v_sql:=$INNER_BLOCK$
+ SELECT $BUILD$||CASE
+ WHEN sc.driver = 'native'
+ THEN 'pgl_ddl_deploy'
+ WHEN sc.driver = 'pglogical'
+ THEN 'pglogical'
+ ELSE 'ERROR-EXCEPTION' END||$BUILD$.replicate_ddl_command($REPLICATE_DDL_COMMAND$
+ SELECT pgl_ddl_deploy.subscriber_command
+ (
+ p_provider_name := $INNER_BLOCK$||COALESCE(quote_literal(c_provider_name), 'NULL')||$INNER_BLOCK$,
+ p_set_name := ARRAY[$INNER_BLOCK$||quote_literal(c_set_name)||$INNER_BLOCK$],
+ p_nspname := $INNER_BLOCK$||COALESCE(quote_literal(v_nspname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_relname := $INNER_BLOCK$||COALESCE(quote_literal(v_relname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_ddl_sql_sent := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_ddl_sql_sent||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_full_ddl := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_full_ddl||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_pid := $INNER_BLOCK$||v_pid::TEXT||$INNER_BLOCK$,
+ p_set_config_id := $INNER_BLOCK$||c_set_config_id::TEXT||$INNER_BLOCK$,
+ p_queue_subscriber_failures := $INNER_BLOCK$||c_queue_subscriber_failures||$INNER_BLOCK$,
+ p_signal_blocking_subscriber_sessions := $INNER_BLOCK$||COALESCE(quote_literal(c_signal_blocking_subscriber_sessions),'NULL')||$INNER_BLOCK$,
+ p_lock_timeout := $INNER_BLOCK$||COALESCE(c_subscriber_lock_timeout, 3000)||$INNER_BLOCK$,
+ p_driver := $INNER_BLOCK$||quote_literal(c_driver)||$INNER_BLOCK$
+ );
+ $REPLICATE_DDL_COMMAND$,
+ --Pipe this DDL command through chosen replication set
+ ARRAY['$INNER_BLOCK$||c_set_name||$INNER_BLOCK$']);
+ $INNER_BLOCK$;
+
+ RAISE DEBUG 'v_sql: %', v_sql;
+ EXECUTE v_sql;
+
+ INSERT INTO pgl_ddl_deploy.events
+ (set_config_id,
+ set_name,
+ pid,
+ executed_at,
+ ddl_sql_raw,
+ ddl_sql_sent,
+ txid)
+ VALUES
+ (c_set_config_id,
+ c_set_name,
+ v_pid,
+ current_timestamp,
+ v_ddl_sql_raw,
+ v_ddl_sql_sent,
+ v_txid);
+ $BUILD$::TEXT AS shared_deploy_logic,
+ $BUILD$
+ ELSEIF (v_match_count > 0 AND v_cmd_count <> v_match_count) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'mixed_objects',
+ v_txid);
+ $BUILD$::TEXT AS shared_mixed_obj_logic,
+ $BUILD$
+ -- Filter out purely PG-internal triggers (alas, "pg_event_trigger_dropped_objects" does not expose "tgisinternal", so we must filter by name)
+ -- Also filter out toast tables since if there are any non-toast operations the toast ones are almost certainly internally generated
+ (SELECT * FROM pg_event_trigger_dropped_objects() WHERE address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_a_%' AND address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_c_%' AND schema_name <> 'pg_toast')
+ $BUILD$::TEXT AS dropped_objects_query,
+
+ $BUILD$
+ /**
+ Catch any exceptions and log in a local table
+ As a safeguard, if even the exception handler fails, exit cleanly but add a server log message
+ **/
+ EXCEPTION WHEN OTHERS THEN
+ GET STACKED DIAGNOSTICS
+ v_context = PG_EXCEPTION_CONTEXT,
+ v_error = MESSAGE_TEXT,
+ v_error_detail = PG_EXCEPTION_DETAIL;
+ BEGIN
+ INSERT INTO pgl_ddl_deploy.exceptions (set_config_id, set_name, pid, executed_at, ddl_sql, err_msg, err_state)
+ VALUES (c_set_config_id, c_set_name, v_pid, current_timestamp, v_sql, format('%s %s %s', v_error, v_context, v_error_detail), SQLSTATE);
+ RAISE WARNING '% (%: % - %)', c_exception_msg, v_error, v_context, v_error_detail;
+ --No matter what, don't let this function block any DDL
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Unhandled exception % %', SQLERRM, SQLSTATE;
+ END;
+ $BUILD$::TEXT AS shared_exception_handler,
+
+ $BUILD$
+ FROM pg_namespace n
+ INNER JOIN pg_class c ON n.oid = c.relnamespace
+ AND c.relpersistence = 'p'
+ WHERE n.nspname ~* c_include_schema_regex
+ AND n.nspname !~* c_exclude_always
+ AND EXISTS (SELECT 1
+ FROM pg_index i
+ WHERE i.indrelid = c.oid
+ AND i.indisprimary)
+ AND NOT EXISTS
+ (SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.name = c_set_name
+ AND rsr.relid = c.oid
+ AND rsr.driver = c_driver)
+ $BUILD$::TEXT AS shared_repl_set_tables,
+
+ $BUILD$
+ SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name ~* c_include_schema_regex
+ AND schema_name !~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_include_schema_regex
+ AND object_identity !~* c_exclude_always)
+ )
+ )
+ OR
+ --include_only_repset_tables usage:
+ (
+ ($BUILD$||include_only_repset_tables||$BUILD$) AND
+ (EXISTS
+ (
+ SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.relid = c.objid
+ AND c.object_type in('table','table column','table constraint')
+ AND rsr.name = '$BUILD$||sc.set_name||$BUILD$'
+ AND rsr.driver = '$BUILD$||sc.driver||$BUILD$'
+ )
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS match_count,
+ SUM(CASE
+ WHEN
+ --include_everything usage still excludes exclude_always regex:
+ (
+ ($BUILD$||include_everything||$BUILD$) AND
+ (
+ (schema_name ~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_exclude_always)
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS exclude_always_match_count
+ $BUILD$::TEXT AS shared_match_count
+FROM pgl_ddl_deploy.rep_set_wrapper() rs
+INNER JOIN pgl_ddl_deploy.set_configs sc ON sc.set_name = rs.name AND sc.driver = rs.driver
+)
+
+, build AS (
+SELECT
+ id,
+ set_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ auto_replication_create_function_name,
+ auto_replication_drop_function_name,
+ auto_replication_unsupported_function_name,
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name,
+
+CASE WHEN driver = 'pglogical' THEN '--no-op pglogical diver'::TEXT
+WHEN driver = 'native' THEN $BUILD$
+DO $$
+BEGIN
+
+IF NOT EXISTS (SELECT 1
+FROM pg_publication_tables
+WHERE pubname = '$BUILD$||set_name||$BUILD$'
+AND schemaname = 'pgl_ddl_deploy'
+AND tablename = 'queue') THEN
+ ALTER PUBLICATION $BUILD$||quote_ident(set_name)||$BUILD$
+ ADD TABLE pgl_ddl_deploy.queue;
+END IF;
+
+END$$;
+$BUILD$
+END AS add_queue_table_to_replication,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$ || auto_replication_create_function_name || $BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , MAX(c.schema_name)
+ , MAX(cl.relname)
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_nspname, v_relname
+ FROM pg_event_trigger_ddl_commands() c
+ LEFT JOIN LATERAL
+ (SELECT cl.relname
+ FROM pg_class cl
+ WHERE cl.oid = c.objid
+ AND c.classid = (SELECT oid FROM pg_class WHERE relname = 'pg_class')
+ -- There should only be one table modified per event trigger
+ -- At least that's the best we will do now
+ LIMIT 1) cl ON TRUE;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_cmd_count = v_match_count))
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension
+ FROM pg_event_trigger_ddl_commands();
+
+ /**
+ Add table to replication set immediately, if required, and only if the set_config includes CREATE TABLE.
+ We do not filter to tags here, because of possibility of multi-statement SQL.
+ Optional ddl_only_replication will never auto-add tables to replication because the
+ purpose is to only replicate keep the structure synchronized on the subscriber with no data.
+ **/
+ IF c_create_tags && '{"CREATE TABLE"}' AND NOT $BUILD$||include_only_repset_tables||$BUILD$ AND NOT $BUILD$||ddl_only_replication||$BUILD$ THEN
+ PERFORM pgl_ddl_deploy.add_table_to_replication(
+ p_driver:=c_driver
+ ,p_set_name:=c_set_name
+ ,p_relation:=c.oid
+ ,p_synchronize_data:=false
+ )
+ $BUILD$||shared_repl_set_tables||$BUILD$;
+ END IF;
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$::TEXT
+END AS auto_replication_function,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_drop_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name !~* '^(pg_catalog|pg_toast)$'
+ AND schema_name !~* c_include_schema_regex)
+ OR (object_type = 'schema'
+ AND object_identity !~* '^(pg_catalog|pg_toast)$'
+ AND object_identity !~* c_include_schema_regex)
+ )
+ )
+ --include_only_repset_tables cannot be used with DROP because
+ --the objects no longer exist to be checked:
+ THEN 1
+ ELSE 0 END) AS excluded_count
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_excluded_count
+ FROM $BUILD$||dropped_objects_query||$BUILD$ as c;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_excluded_count = 0))
+
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ TG_TAG,
+ object_type,
+ schema_name,
+ object_identity,
+ NULL
+ FROM $BUILD$||dropped_objects_query||$BUILD$ as c;
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_drop_function,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_unsupported_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count
+ FROM pg_event_trigger_ddl_commands() c;
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0)
+ THEN
+
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'unsupported_command',
+ v_txid);
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_unsupported_function,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(create_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$ || auto_replication_create_function_name || $BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_trigger,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ON sql_drop
+WHEN TAG IN('$BUILD$||array_to_string(drop_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$||auto_replication_drop_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_drop_trigger,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(pgl_ddl_deploy.unsupported_tags(),$$','$$)||$BUILD$')
+EXECUTE PROCEDURE $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_unsupported_trigger,
+
+$BUILD$
+DROP TABLE IF EXISTS tmp_objs;
+CREATE TEMP TABLE tmp_objs (obj_type, obj_name) AS (
+VALUES
+('EVENT TRIGGER','$BUILD$||auto_replication_create_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_drop_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_unsupported_trigger_name||$BUILD$'),
+('FUNCTION','$BUILD$||auto_replication_create_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_drop_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_unsupported_function_name||$BUILD$()')
+);
+
+SELECT pgl_ddl_deploy.drop_ext_object(obj_type, obj_name)
+FROM tmp_objs;
+DROP EVENT TRIGGER IF EXISTS $BUILD$||auto_replication_create_trigger_name||', '||auto_replication_drop_trigger_name||', '||auto_replication_unsupported_trigger_name||$BUILD$;
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_create_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_drop_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$
+ AS undeploy_sql
+FROM vars)
+
+SELECT
+ b.id,
+ b.set_name,
+ b.include_schema_regex,
+ b.include_only_repset_tables,
+ b.include_everything,
+ b.signal_blocking_subscriber_sessions,
+ b.subscriber_lock_timeout,
+ b.auto_replication_create_function_name,
+ b.auto_replication_drop_function_name,
+ b.auto_replication_unsupported_function_name,
+ b.auto_replication_create_trigger_name,
+ b.auto_replication_drop_trigger_name,
+ b.auto_replication_unsupported_trigger_name,
+ b.auto_replication_function,
+ b.auto_replication_drop_function,
+ b.auto_replication_unsupported_function,
+ b.auto_replication_trigger,
+ b.auto_replication_drop_trigger,
+ b.auto_replication_unsupported_trigger,
+ b.undeploy_sql,
+ b.undeploy_sql||
+ b.add_queue_table_to_replication||$BUILD$
+ $BUILD$||auto_replication_function||$BUILD$
+ $BUILD$||auto_replication_drop_function||$BUILD$
+ $BUILD$||auto_replication_unsupported_function||$BUILD$
+ $BUILD$||auto_replication_trigger||$BUILD$
+ $BUILD$||auto_replication_drop_trigger||$BUILD$
+ $BUILD$||auto_replication_unsupported_trigger||$BUILD$
+ SELECT pgl_ddl_deploy.add_ext_object(obj_type, obj_name)
+ FROM tmp_objs;
+ $BUILD$ AS deploy_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ DISABLE;
+ $BUILD$ AS disable_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ENABLE;
+ $BUILD$ AS enable_sql,
+ EXISTS (SELECT 1
+ FROM pg_event_trigger
+ WHERE evtname IN(
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name
+ )
+ AND evtenabled IN('O','R','A')
+ ) AS is_deployed
+FROM build b;
+
+
diff --git a/pgl_ddl_deploy--2.4.sql b/pgl_ddl_deploy--2.4.sql
new file mode 100644
index 0000000..01649fc
--- /dev/null
+++ b/pgl_ddl_deploy--2.4.sql
@@ -0,0 +1,5952 @@
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+CREATE FUNCTION pgl_ddl_deploy.sql_command_tags(p_sql TEXT)
+RETURNS TEXT[] AS
+'MODULE_PATHNAME', 'sql_command_tags'
+LANGUAGE C VOLATILE STRICT;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.add_ext_object
+ (p_type text
+ , p_full_obj_name text)
+RETURNS VOID AS
+$BODY$
+BEGIN
+PERFORM pgl_ddl_deploy.toggle_ext_object(p_type, p_full_obj_name, 'ADD');
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.drop_ext_object
+ (p_type text
+ , p_full_obj_name text)
+RETURNS VOID AS
+$BODY$
+BEGIN
+PERFORM pgl_ddl_deploy.toggle_ext_object(p_type, p_full_obj_name, 'DROP');
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.toggle_ext_object
+ (p_type text
+ , p_full_obj_name text
+ , p_toggle text)
+RETURNS VOID AS
+$BODY$
+DECLARE
+ c_valid_types TEXT[] = ARRAY['EVENT TRIGGER','FUNCTION','VIEW'];
+ c_valid_toggles TEXT[] = ARRAY['ADD','DROP'];
+BEGIN
+
+IF NOT (SELECT ARRAY[p_type] && c_valid_types) THEN
+ RAISE EXCEPTION 'Must pass one of % as 1st arg.', array_to_string(c_valid_types);
+END IF;
+
+IF NOT (SELECT ARRAY[p_toggle] && c_valid_toggles) THEN
+ RAISE EXCEPTION 'Must pass one of % as 3rd arg.', array_to_string(c_valid_toggles);
+END IF;
+
+EXECUTE 'ALTER EXTENSION pgl_ddl_deploy '||p_toggle||' '||p_type||' '||p_full_obj_name;
+
+EXCEPTION
+ WHEN undefined_function THEN
+ RETURN;
+ WHEN undefined_object THEN
+ RETURN;
+ WHEN object_not_in_prerequisite_state THEN
+ RETURN;
+END;
+$BODY$
+LANGUAGE plpgsql;
+CREATE FUNCTION pgl_ddl_deploy.exclude_regex()
+RETURNS TEXT AS
+$BODY$
+SELECT '^(pg_catalog|information_schema|pg_temp|pg_toast|pgl_ddl_deploy|pglogical).*'::TEXT;
+$BODY$
+LANGUAGE SQL IMMUTABLE;
+
+CREATE FUNCTION pgl_ddl_deploy.blacklisted_tags()
+RETURNS TEXT[] AS
+$BODY$
+SELECT '{
+ INSERT,
+ UPDATE,
+ DELETE,
+ TRUNCATE,
+ SELECT,
+ ROLLBACK,
+ "CREATE EXTENSION",
+ "ALTER EXTENSION",
+ "DROP EXTENSION"}'::TEXT[];
+$BODY$
+LANGUAGE SQL IMMUTABLE;
+
+CREATE TABLE pgl_ddl_deploy.set_configs (
+ set_name NAME PRIMARY KEY,
+ include_schema_regex TEXT NOT NULL,
+ lock_safe_deployment BOOLEAN DEFAULT FALSE NOT NULL,
+ allow_multi_statements BOOLEAN DEFAULT TRUE NOT NULL,
+ CONSTRAINT valid_regex CHECK (CASE WHEN regexp_replace('',include_schema_regex,'') = '' THEN TRUE ELSE FALSE END)
+ );
+
+SELECT pg_catalog.pg_extension_config_dump('pgl_ddl_deploy.set_configs', '');
+
+CREATE TABLE pgl_ddl_deploy.events (
+ id SERIAL PRIMARY KEY,
+ set_name NAME,
+ pid INT,
+ executed_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
+ ddl_sql_raw TEXT,
+ ddl_sql_sent TEXT,
+ txid BIGINT
+ );
+
+CREATE UNIQUE INDEX ON pgl_ddl_deploy.events (set_name, pid, txid, md5(ddl_sql_raw));
+
+CREATE TABLE pgl_ddl_deploy.exceptions (
+ id SERIAL PRIMARY KEY,
+ set_name NAME,
+ pid INT,
+ executed_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
+ ddl_sql TEXT,
+ err_msg TEXT,
+ err_state TEXT);
+
+CREATE TABLE pgl_ddl_deploy.unhandled (
+ id SERIAL PRIMARY KEY,
+ set_name NAME,
+ pid INT,
+ executed_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
+ ddl_sql_raw TEXT,
+ command_tag TEXT,
+ reason TEXT,
+ txid BIGINT,
+ CONSTRAINT valid_reason CHECK (reason IN('mixed_objects','rejected_command_tags','rejected_multi_statement','unsupported_command'))
+ );
+
+CREATE UNIQUE INDEX ON pgl_ddl_deploy.unhandled (set_name, pid, txid, md5(ddl_sql_raw));
+
+CREATE FUNCTION pgl_ddl_deploy.log_unhandled
+(p_set_name TEXT,
+ p_pid INT,
+ p_ddl_sql_raw TEXT,
+ p_command_tag TEXT,
+ p_reason TEXT,
+ p_txid BIGINT)
+RETURNS VOID AS
+$BODY$
+DECLARE
+ c_unhandled_msg TEXT = 'Unhandled deployment logged in pgl_ddl_deploy.unhandled';
+BEGIN
+INSERT INTO pgl_ddl_deploy.unhandled
+ (set_name,
+ pid,
+ executed_at,
+ ddl_sql_raw,
+ command_tag,
+ reason,
+ txid)
+VALUES
+ (p_set_name,
+ p_pid,
+ current_timestamp,
+ p_ddl_sql_raw,
+ p_command_tag,
+ p_reason,
+ p_txid);
+RAISE WARNING '%', c_unhandled_msg;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE TABLE pgl_ddl_deploy.subscriber_logs (
+ id SERIAL PRIMARY KEY,
+ set_name NAME,
+ provider_pid INT,
+ subscriber_pid INT,
+ executed_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
+ ddl_sql TEXT);
+
+CREATE TABLE pgl_ddl_deploy.commands (
+ id SERIAL PRIMARY KEY,
+ set_name NAME,
+ pid INT,
+ txid BIGINT,
+ classid Oid,
+ objid Oid,
+ objsubid integer,
+ command_tag text,
+ object_type text,
+ schema_name text,
+ object_identity text,
+ in_extension bool);
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.lock_safe_executor(p_sql TEXT)
+RETURNS VOID AS $BODY$
+BEGIN
+SET lock_timeout TO '10ms';
+LOOP
+ BEGIN
+ EXECUTE p_sql;
+ EXIT;
+ EXCEPTION
+ WHEN lock_not_available
+ THEN RAISE WARNING 'Could not obtain immediate lock for SQL %, retrying', p_sql;
+ PERFORM pg_sleep(3);
+ WHEN OTHERS THEN
+ RAISE;
+ END;
+END LOOP;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deploy(p_set_name text) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_deployable BOOLEAN;
+ v_result BOOLEAN;
+BEGIN
+ SELECT pgl_ddl_deploy.deployment_check(p_set_name) INTO v_deployable;
+ IF v_deployable THEN
+ SELECT pgl_ddl_deploy.schema_execute(p_set_name, 'deploy_sql') INTO v_result;
+ RETURN v_result;
+ ELSE
+ RETURN v_deployable;
+ END IF;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.enable(p_set_name text) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_deployable BOOLEAN;
+ v_result BOOLEAN;
+BEGIN
+ SELECT pgl_ddl_deploy.deployment_check(p_set_name) INTO v_deployable;
+ IF v_deployable THEN
+ SELECT pgl_ddl_deploy.schema_execute(p_set_name, 'enable_sql') INTO v_result;
+ RETURN v_result;
+ ELSE
+ RETURN v_deployable;
+ END IF;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.disable(p_set_name text) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_result BOOLEAN;
+BEGIN
+ SELECT pgl_ddl_deploy.schema_execute(p_set_name, 'disable_sql') INTO v_result;
+ RETURN v_result;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.schema_execute(p_set_name text, p_field_name text) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_in_sql TEXT;
+ v_out_sql TEXT;
+BEGIN
+ v_in_sql = $$(SELECT $$||p_field_name||$$
+ FROM pgl_ddl_deploy.event_trigger_schema
+ WHERE set_name = '$$||p_set_name||$$');$$;
+ EXECUTE v_in_sql INTO v_out_sql;
+ IF v_out_sql IS NULL THEN
+ RETURN FALSE;
+ ELSE
+ EXECUTE v_out_sql;
+ RETURN TRUE;
+ END IF;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+
+GRANT USAGE ON SCHEMA pgl_ddl_deploy TO PUBLIC;
+DO $$ BEGIN
+IF EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pglogical') THEN
+GRANT USAGE ON SCHEMA pglogical TO PUBLIC; REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA pglogical FROM PUBLIC;
+END IF;
+IF EXISTS (SELECT 1 FROM pg_proc p INNER JOIN pg_namespace n ON n.oid = p.pronamespace WHERE proname = 'dependency_check_trigger' AND nspname = 'pglogical') THEN
+ GRANT EXECUTE ON FUNCTION pglogical.dependency_check_trigger() TO PUBLIC;
+END IF;
+IF EXISTS (SELECT 1 FROM pg_proc p INNER JOIN pg_namespace n ON n.oid = p.pronamespace WHERE proname = 'truncate_trigger_add' AND nspname = 'pglogical') THEN
+ GRANT EXECUTE ON FUNCTION pglogical.truncate_trigger_add() TO PUBLIC;
+END IF;
+END$$;
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.sql_command_tags(text) FROM PUBLIC;
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+/****
+We first need to drop existing event triggers and functions, because the naming convention is
+changing
+ */
+DROP TABLE IF EXISTS tmp_objs;
+CREATE TEMP TABLE tmp_objs AS
+WITH old_named_objects AS
+(SELECT set_name,
+
+ 'pgl_ddl_deploy.auto_replicate_ddl_'||set_name||'()' AS auto_replication_function_name,
+ 'pgl_ddl_deploy.auto_replicate_ddl_drop_'||set_name||'()' AS auto_replication_drop_function_name,
+ 'pgl_ddl_deploy.auto_replicate_ddl_unsupported_'||set_name||'()' AS auto_replication_unsupported_function_name,
+ 'auto_replicate_ddl_'||set_name AS auto_replication_trigger_name,
+ 'auto_replicate_ddl_drop_'||set_name AS auto_replication_drop_trigger_name,
+ 'auto_replicate_ddl_unsupported_'||set_name AS auto_replication_unsupported_trigger_name
+
+FROM pgl_ddl_deploy.set_configs)
+
+SELECT set_name, 'EVENT TRIGGER' AS obj_type, auto_replication_trigger_name AS obj_name FROM old_named_objects UNION ALL
+SELECT set_name, 'EVENT TRIGGER' AS obj_type, auto_replication_drop_trigger_name AS obj_name FROM old_named_objects UNION ALL
+SELECT set_name, 'EVENT TRIGGER' AS obj_type, auto_replication_unsupported_trigger_name AS obj_name FROM old_named_objects UNION ALL
+SELECT set_name, 'FUNCTION' AS obj_type, auto_replication_function_name AS obj_name FROM old_named_objects UNION ALL
+SELECT set_name, 'FUNCTION' AS obj_type, auto_replication_drop_function_name AS obj_name FROM old_named_objects UNION ALL
+SELECT set_name, 'FUNCTION' AS obj_type, auto_replication_unsupported_function_name AS obj_name FROM old_named_objects
+;
+
+SELECT pgl_ddl_deploy.drop_ext_object(obj_type, obj_name)
+FROM tmp_objs;
+
+DO $BUILD$
+DECLARE
+ v_rec RECORD;
+ v_sql TEXT;
+BEGIN
+
+FOR v_rec IN
+ SELECT * FROM tmp_objs WHERE obj_type = 'EVENT TRIGGER'
+LOOP
+
+v_sql = $$DROP EVENT TRIGGER IF EXISTS $$||v_rec.obj_name||$$;$$;
+EXECUTE v_sql;
+RAISE WARNING 'Event trigger % dropped', v_rec.obj_name;
+
+END LOOP;
+
+FOR v_rec IN
+ SELECT * FROM tmp_objs WHERE obj_type = 'FUNCTION'
+LOOP
+v_sql = $$DROP FUNCTION IF EXISTS $$||v_rec.obj_name||$$;$$;
+EXECUTE v_sql;
+RAISE WARNING 'Function % dropped', v_rec.obj_name;
+
+END LOOP;
+
+FOR v_rec IN
+ SELECT DISTINCT set_name FROM tmp_objs
+LOOP
+RAISE WARNING $$Objects changed - you must manually re-deploy using pgl_ddl_deploy.deploy('%')$$, v_rec.set_name;
+END LOOP;
+
+END
+$BUILD$;
+
+--If you don't do this, it will be part of the extension!
+DROP TABLE tmp_objs;
+
+CREATE FUNCTION pgl_ddl_deploy.standard_create_tags()
+RETURNS TEXT[] AS
+$BODY$
+SELECT '{
+ "ALTER TABLE"
+ ,"CREATE SEQUENCE"
+ ,"ALTER SEQUENCE"
+ ,"CREATE SCHEMA"
+ ,"CREATE TABLE"
+ ,"CREATE FUNCTION"
+ ,"ALTER FUNCTION"
+ ,"CREATE TYPE"
+ ,"ALTER TYPE"
+ ,"CREATE VIEW"
+ ,"ALTER VIEW"
+ }'::TEXT[];
+$BODY$
+LANGUAGE SQL IMMUTABLE;
+
+CREATE FUNCTION pgl_ddl_deploy.standard_drop_tags()
+RETURNS TEXT[] AS
+$BODY$
+SELECT '{
+ "DROP SCHEMA"
+ ,"DROP TABLE"
+ ,"DROP FUNCTION"
+ ,"DROP TYPE"
+ ,"DROP VIEW"
+ ,"DROP SEQUENCE"
+ }'::TEXT[];
+$BODY$
+LANGUAGE SQL IMMUTABLE;
+
+CREATE FUNCTION pgl_ddl_deploy.unsupported_tags()
+RETURNS TEXT[] AS
+$BODY$
+SELECT '{
+ "CREATE TABLE AS"
+ ,"SELECT INTO"
+ }'::TEXT[];
+$BODY$
+LANGUAGE SQL IMMUTABLE;
+
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN id SERIAL;
+ALTER TABLE pgl_ddl_deploy.set_configs DROP CONSTRAINT set_configs_pkey;
+ALTER TABLE pgl_ddl_deploy.set_configs ADD PRIMARY KEY (id);
+ALTER TABLE pgl_ddl_deploy.commands ADD COLUMN set_config_id INT REFERENCES pgl_ddl_deploy.set_configs (id);
+ALTER TABLE pgl_ddl_deploy.events ADD COLUMN set_config_id INT REFERENCES pgl_ddl_deploy.set_configs (id);
+ALTER TABLE pgl_ddl_deploy.unhandled ADD COLUMN set_config_id INT REFERENCES pgl_ddl_deploy.set_configs (id);
+ALTER TABLE pgl_ddl_deploy.exceptions ADD COLUMN set_config_id INT REFERENCES pgl_ddl_deploy.set_configs (id);
+
+ALTER EXTENSION pgl_ddl_deploy
+DROP FUNCTION pgl_ddl_deploy.log_unhandled
+(TEXT,
+ INT,
+ TEXT,
+ TEXT,
+ TEXT,
+ BIGINT);
+DROP FUNCTION pgl_ddl_deploy.log_unhandled
+(TEXT,
+ INT,
+ TEXT,
+ TEXT,
+ TEXT,
+ BIGINT);
+CREATE FUNCTION pgl_ddl_deploy.log_unhandled
+(p_set_config_id INT,
+ p_set_name TEXT,
+ p_pid INT,
+ p_ddl_sql_raw TEXT,
+ p_command_tag TEXT,
+ p_reason TEXT,
+ p_txid BIGINT)
+RETURNS VOID AS
+$BODY$
+DECLARE
+ c_unhandled_msg TEXT = 'Unhandled deployment logged in pgl_ddl_deploy.unhandled';
+BEGIN
+INSERT INTO pgl_ddl_deploy.unhandled
+ (set_config_id,
+ set_name,
+ pid,
+ executed_at,
+ ddl_sql_raw,
+ command_tag,
+ reason,
+ txid)
+VALUES
+ (p_set_config_id,
+ p_set_name,
+ p_pid,
+ current_timestamp,
+ p_ddl_sql_raw,
+ p_command_tag,
+ p_reason,
+ p_txid);
+RAISE WARNING '%', c_unhandled_msg;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+--Allow specific tables or include regex
+ALTER TABLE pgl_ddl_deploy.set_configs ALTER COLUMN include_schema_regex DROP NOT NULL;
+ALTER TABLE pgl_ddl_deploy.set_configs DROP CONSTRAINT valid_regex;
+ALTER TABLE pgl_ddl_deploy.set_configs ADD CONSTRAINT valid_regex CHECK (include_schema_regex IS NULL OR (CASE WHEN regexp_replace('',include_schema_regex,'') = '' THEN TRUE ELSE FALSE END));
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN include_only_repset_tables BOOLEAN NOT NULL DEFAULT FALSE;
+ALTER TABLE pgl_ddl_deploy.set_configs ADD CONSTRAINT repset_tables_or_regex_inclusion CHECK ((include_schema_regex IS NOT NULL AND NOT include_only_repset_tables) OR (include_only_repset_tables AND include_schema_regex IS NULL));
+
+--Customize command tags
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN create_tags TEXT[];
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN drop_tags TEXT[];
+UPDATE pgl_ddl_deploy.set_configs
+SET create_tags = pgl_ddl_deploy.standard_create_tags(),
+ drop_tags = pgl_ddl_deploy.standard_drop_tags();
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN blacklisted_tags TEXT[] DEFAULT pgl_ddl_deploy.blacklisted_tags();
+
+--Allow failures
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN queue_subscriber_failures BOOLEAN NOT NULL DEFAULT FALSE;
+ALTER TABLE pgl_ddl_deploy.set_configs ADD CONSTRAINT repset_tables_only_alter_table CHECK ((NOT include_only_repset_tables) OR (include_only_repset_tables AND create_tags = '{"ALTER TABLE"}' AND drop_tags IS NULL));
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.unique_tags()
+RETURNS TRIGGER AS
+$BODY$
+BEGIN
+ IF EXISTS (
+ SELECT 1
+ FROM pgl_ddl_deploy.set_configs
+ WHERE id <> NEW.id
+ AND set_name = NEW.set_name
+ AND (create_tags && NEW.create_tags
+ OR drop_tags && NEW.drop_tags)) THEN
+ RAISE EXCEPTION $$Another set_config already exists for '%' with overlapping create_tags or drop_tags.
+ Command tags must only appear once per set_name even if using multiple set_configs.
+ $$, NEW.set_name;
+ END IF;
+ RETURN NEW;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE TRIGGER unique_tags
+BEFORE INSERT OR UPDATE ON pgl_ddl_deploy.set_configs
+FOR EACH ROW EXECUTE PROCEDURE pgl_ddl_deploy.unique_tags();
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.set_tag_defaults()
+RETURNS TRIGGER AS
+$BODY$
+BEGIN
+IF NEW.create_tags IS NULL THEN
+ NEW.create_tags = CASE WHEN NEW.include_only_repset_tables THEN '{"ALTER TABLE"}' ELSE pgl_ddl_deploy.standard_create_tags() END;
+END IF;
+IF NEW.drop_tags IS NULL THEN
+ NEW.drop_tags = CASE WHEN NEW.include_only_repset_tables THEN NULL ELSE pgl_ddl_deploy.standard_drop_tags() END;
+END IF;
+RETURN NEW;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE TRIGGER set_tag_defaults
+BEFORE INSERT OR UPDATE ON pgl_ddl_deploy.set_configs
+FOR EACH ROW EXECUTE PROCEDURE pgl_ddl_deploy.set_tag_defaults();
+
+ALTER TABLE pgl_ddl_deploy.subscriber_logs
+ ADD COLUMN full_ddl_sql TEXT,
+ ADD COLUMN origin_subscriber_log_id INT NULL REFERENCES pgl_ddl_deploy.subscriber_logs(id),
+ ADD COLUMN next_subscriber_log_id INT NULL REFERENCES pgl_ddl_deploy.subscriber_logs(id),
+ ADD COLUMN provider_node_name TEXT,
+ ADD COLUMN provider_set_config_id INT,
+ ADD COLUMN executed_as_role TEXT DEFAULT current_role,
+ ADD COLUMN retrying BOOLEAN NOT NULL DEFAULT FALSE,
+ ADD COLUMN succeeded BOOLEAN NULL,
+ ADD COLUMN error_message TEXT;
+
+CREATE FUNCTION pgl_ddl_deploy.set_origin_subscriber_log_id()
+RETURNS TRIGGER AS
+$BODY$
+BEGIN
+NEW.origin_subscriber_log_id = NEW.id;
+RETURN NEW;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE TRIGGER set_origin_subscriber_log_id
+BEFORE INSERT ON pgl_ddl_deploy.subscriber_logs
+FOR EACH ROW WHEN (NEW.origin_subscriber_log_id IS NULL)
+EXECUTE PROCEDURE pgl_ddl_deploy.set_origin_subscriber_log_id();
+
+ALTER TABLE pgl_ddl_deploy.subscriber_logs ENABLE REPLICA TRIGGER set_origin_subscriber_log_id;
+
+CREATE UNIQUE INDEX unique_untried ON pgl_ddl_deploy.subscriber_logs (origin_subscriber_log_id) WHERE NOT succeeded AND next_subscriber_log_id IS NULL AND NOT retrying;
+CREATE UNIQUE INDEX unique_retrying ON pgl_ddl_deploy.subscriber_logs (origin_subscriber_log_id) WHERE retrying;
+CREATE UNIQUE INDEX unique_succeeded ON pgl_ddl_deploy.subscriber_logs (origin_subscriber_log_id) WHERE succeeded;
+
+CREATE FUNCTION pgl_ddl_deploy.fail_queued_attempt(p_subscriber_log_id INT, p_error_message TEXT)
+RETURNS VOID AS
+$BODY$
+DECLARE
+ v_new_subscriber_log_id INT;
+BEGIN
+
+INSERT INTO pgl_ddl_deploy.subscriber_logs
+ (set_name,
+ provider_pid,
+ subscriber_pid,
+ ddl_sql,
+ full_ddl_sql,
+ origin_subscriber_log_id,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ error_message,
+ succeeded)
+SELECT
+ set_name,
+ provider_pid,
+ pg_backend_pid(),
+ ddl_sql,
+ full_ddl_sql,
+ origin_subscriber_log_id,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ p_error_message,
+ FALSE
+FROM pgl_ddl_deploy.subscriber_logs
+WHERE id = p_subscriber_log_id
+RETURNING id INTO v_new_subscriber_log_id;
+
+UPDATE pgl_ddl_deploy.subscriber_logs
+SET next_subscriber_log_id = v_new_subscriber_log_id
+WHERE id = p_subscriber_log_id;
+
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE FUNCTION pgl_ddl_deploy.retry_subscriber_log(p_subscriber_log_id INT)
+RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_sql TEXT;
+ v_role TEXT;
+ v_return BOOLEAN;
+BEGIN
+ IF (SELECT retrying FROM pgl_ddl_deploy.subscriber_logs
+ WHERE id = p_subscriber_log_id) = TRUE THEN
+ RAISE WARNING 'This subscriber_log_id is already executing. No action will be taken.';
+ RETURN FALSE;
+ END IF;
+
+ SELECT full_ddl_sql, executed_as_role
+ INTO v_sql, v_role
+ FROM pgl_ddl_deploy.subscriber_logs
+ WHERE id = p_subscriber_log_id;
+
+ UPDATE pgl_ddl_deploy.subscriber_logs
+ SET retrying = TRUE
+ WHERE id = p_subscriber_log_id;
+
+ BEGIN
+ /**
+ This needs to be a DO block because currently,the final SQL sent to subscriber is always within a DO block
+ */
+ v_sql = $$
+ DO $RETRY$
+ BEGIN
+
+ SET ROLE $$||quote_ident(v_role)||$$;
+
+ $$||v_sql||$$
+
+ END$RETRY$;
+ $$;
+ EXECUTE v_sql;
+ RESET ROLE;
+
+ WITH success AS (
+ INSERT INTO pgl_ddl_deploy.subscriber_logs
+ (set_name,
+ provider_pid,
+ subscriber_pid,
+ ddl_sql,
+ full_ddl_sql,
+ origin_subscriber_log_id,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ succeeded)
+ SELECT
+ set_name,
+ provider_pid,
+ pg_backend_pid(),
+ ddl_sql,
+ full_ddl_sql,
+ origin_subscriber_log_id,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ TRUE
+ FROM pgl_ddl_deploy.subscriber_logs
+ WHERE id = p_subscriber_log_id
+ RETURNING *
+ )
+
+ UPDATE pgl_ddl_deploy.subscriber_logs
+ SET next_subscriber_log_id = (SELECT id FROM success)
+ WHERE id = p_subscriber_log_id;
+
+ v_return = TRUE;
+
+ EXCEPTION WHEN OTHERS THEN
+ PERFORM pgl_ddl_deploy.fail_queued_attempt(p_subscriber_log_id, SQLERRM);
+ v_return = FALSE;
+ END;
+
+ UPDATE pgl_ddl_deploy.subscriber_logs
+ SET retrying = FALSE
+ WHERE id = p_subscriber_log_id;
+
+ RETURN v_return;
+
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE FUNCTION pgl_ddl_deploy.retry_all_subscriber_logs()
+RETURNS BOOLEAN[] AS
+$BODY$
+DECLARE
+ v_rec RECORD;
+ v_result BOOLEAN;
+ v_results BOOLEAN[];
+BEGIN
+
+FOR v_rec IN
+ SELECT
+ rq.id
+ FROM pgl_ddl_deploy.subscriber_logs rq
+ INNER JOIN pgl_ddl_deploy.subscriber_logs rqo ON rqo.id = rq.origin_subscriber_log_id
+ WHERE NOT rq.succeeded AND rq.next_subscriber_log_id IS NULL AND NOT rq.retrying
+ ORDER BY rqo.executed_at ASC, rqo.origin_subscriber_log_id ASC
+LOOP
+
+ SELECT pgl_ddl_deploy.retry_subscriber_log(v_rec.id) INTO v_result;
+ v_results = array_append(v_results, v_result);
+ IF NOT v_result THEN
+ RETURN v_results;
+ END IF;
+
+END LOOP;
+
+RETURN v_results;
+
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+--Allow a mechanism to mark unhandled and exceptions as resolved for monitoring purposes
+ALTER TABLE pgl_ddl_deploy.unhandled ADD COLUMN resolved BOOLEAN NOT NULL DEFAULT FALSE;
+ALTER TABLE pgl_ddl_deploy.unhandled ADD COLUMN resolved_notes TEXT NULL;
+ALTER TABLE pgl_ddl_deploy.exceptions ADD COLUMN resolved BOOLEAN NOT NULL DEFAULT FALSE;
+ALTER TABLE pgl_ddl_deploy.exceptions ADD COLUMN resolved_notes TEXT NULL;
+
+CREATE FUNCTION pgl_ddl_deploy.resolve_unhandled(p_unhandled_id INT, p_notes TEXT = NULL)
+RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_row_count INT;
+BEGIN
+ UPDATE pgl_ddl_deploy.unhandled
+ SET resolved = TRUE,
+ resolved_notes = p_notes
+ WHERE id = p_unhandled_id;
+
+ GET DIAGNOSTICS v_row_count = ROW_COUNT;
+ RETURN (v_row_count > 0);
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE FUNCTION pgl_ddl_deploy.resolve_exception(p_exception_id INT, p_notes TEXT = NULL)
+RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_row_count INT;
+BEGIN
+ UPDATE pgl_ddl_deploy.exceptions
+ SET resolved = TRUE,
+ resolved_notes = p_notes
+ WHERE id = p_exception_id;
+
+ GET DIAGNOSTICS v_row_count = ROW_COUNT;
+ RETURN (v_row_count > 0);
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deployment_check(p_set_name text) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_set_config_id INT;
+ c_include_schema_regex TEXT;
+BEGIN
+
+IF NOT EXISTS (SELECT 1 FROM pgl_ddl_deploy.set_configs WHERE set_name = p_set_name) THEN
+ RETURN FALSE;
+END IF;
+
+--This check only applicable to non-include_only_repset_tables and sets using CREATE TABLE events
+SELECT id, include_schema_regex
+INTO c_set_config_id, c_include_schema_regex
+FROM pgl_ddl_deploy.set_configs
+WHERE set_name = p_set_name
+ AND NOT include_only_repset_tables
+ AND create_tags && '{"CREATE TABLE"}'::TEXT[];
+
+RETURN pgl_ddl_deploy.deployment_check_count(c_set_config_id, p_set_name, c_include_schema_regex);
+
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deployment_check(p_set_config_id int) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_set_config_id INT;
+ c_include_schema_regex TEXT;
+ c_set_name TEXT;
+BEGIN
+
+IF NOT EXISTS (SELECT 1 FROM pgl_ddl_deploy.set_configs WHERE id = p_set_config_id) THEN
+ RETURN FALSE;
+END IF;
+
+--This check only applicable to non-include_only_repset_tables and sets using CREATE TABLE events
+--We re-assign set_config_id because we want to know if no records are found, leading to NULL
+SELECT id, include_schema_regex, set_name
+INTO c_set_config_id, c_include_schema_regex, c_set_name
+FROM pgl_ddl_deploy.set_configs
+WHERE id = p_set_config_id
+ AND NOT include_only_repset_tables
+ AND create_tags && '{"CREATE TABLE"}'::TEXT[];
+
+RETURN pgl_ddl_deploy.deployment_check_count(c_set_config_id, c_set_name, c_include_schema_regex);
+
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deploy(p_set_config_id int) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_deployable BOOLEAN;
+ v_result BOOLEAN;
+BEGIN
+ SELECT pgl_ddl_deploy.deployment_check(p_set_config_id) INTO v_deployable;
+ IF v_deployable THEN
+ SELECT pgl_ddl_deploy.schema_execute(p_set_config_id, 'deploy_sql') INTO v_result;
+ RETURN v_result;
+ ELSE
+ RETURN v_deployable;
+ END IF;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.enable(p_set_config_id int) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_deployable BOOLEAN;
+ v_result BOOLEAN;
+BEGIN
+ SELECT pgl_ddl_deploy.deployment_check(p_set_config_id) INTO v_deployable;
+ IF v_deployable THEN
+ SELECT pgl_ddl_deploy.schema_execute(p_set_config_id, 'enable_sql') INTO v_result;
+ RETURN v_result;
+ ELSE
+ RETURN v_deployable;
+ END IF;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.disable(p_set_config_id int) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_result BOOLEAN;
+BEGIN
+ SELECT pgl_ddl_deploy.schema_execute(p_set_config_id, 'disable_sql') INTO v_result;
+ RETURN v_result;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.schema_execute(p_set_name text, p_field_name text) RETURNS BOOLEAN AS
+$BODY$
+/****
+This function will deploy SQL for all set_configs with given set_name, since this is now allowed.
+The version of this function with (int, text) uses a single set_config_id to deploy
+ */
+DECLARE
+ v_rec RECORD;
+ v_in_sql TEXT;
+ v_out_sql TEXT;
+BEGIN
+ FOR v_rec IN
+ SELECT id
+ FROM pgl_ddl_deploy.set_configs
+ WHERE set_name = p_set_name
+ LOOP
+ v_in_sql = $$(SELECT $$||p_field_name||$$
+ FROM pgl_ddl_deploy.event_trigger_schema
+ WHERE id = $$||v_rec.id||$$
+ AND set_name = '$$||p_set_name||$$');$$;
+ EXECUTE v_in_sql INTO v_out_sql;
+ IF v_out_sql IS NULL THEN
+ RAISE WARNING 'Failed execution for id % set %', v_rec.id, p_set_name;
+ RETURN FALSE;
+ ELSE
+ EXECUTE v_out_sql;
+ END IF;
+
+ END LOOP;
+ RETURN TRUE;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.schema_execute(p_set_config_id int, p_field_name text) RETURNS BOOLEAN AS
+$BODY$
+DECLARE
+ v_rec RECORD;
+ v_in_sql TEXT;
+ v_out_sql TEXT;
+BEGIN
+ v_in_sql = $$(SELECT $$||p_field_name||$$
+ FROM pgl_ddl_deploy.event_trigger_schema
+ WHERE id = $$||p_set_config_id||$$);$$;
+ EXECUTE v_in_sql INTO v_out_sql;
+ IF v_out_sql IS NULL THEN
+ RAISE WARNING 'Failed execution for id % set %', p_set_config_id, (SELECT set_name FROM pgl_ddl_deploy.set_configs WHERE id = p_set_config_id);
+ RETURN FALSE;
+ ELSE
+ EXECUTE v_out_sql;
+ RETURN TRUE;
+ END IF;
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+
+--Just do this to avoid unneeded complexity with dependency_update
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.undeploy(p_set_config_id int) RETURNS BOOLEAN AS
+$BODY$
+BEGIN
+ RETURN pgl_ddl_deploy.schema_execute(p_set_config_id, 'undeploy_sql');
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.undeploy(p_set_name text) RETURNS BOOLEAN AS
+$BODY$
+BEGIN
+ RETURN pgl_ddl_deploy.schema_execute(p_set_name, 'undeploy_sql');
+END;
+$BODY$
+LANGUAGE plpgsql;
+
+
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN exclude_alter_table_subcommands TEXT[];
+
+ALTER TABLE pgl_ddl_deploy.set_configs DROP CONSTRAINT repset_tables_only_alter_table;
+
+SELECT pg_catalog.pg_extension_config_dump('pgl_ddl_deploy.set_configs_id_seq', '');
+
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN ddl_only_replication BOOLEAN NOT NULL DEFAULT FALSE;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.rep_set_table_wrapper()
+ RETURNS TABLE (set_id OID, set_reloid REGCLASS)
+ LANGUAGE plpgsql
+ SECURITY DEFINER
+AS $function$
+/*****
+This handles the rename of pglogical.replication_set_relation to pglogical.replication_set_table from version 1 to 2
+ */
+BEGIN
+
+IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'pglogical' AND tablename = 'replication_set_table') THEN
+ RETURN QUERY
+ SELECT r.set_id, r.set_reloid
+ FROM pglogical.replication_set_table r;
+
+ELSEIF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'pglogical' AND tablename = 'replication_set_relation') THEN
+ RETURN QUERY
+ SELECT r.set_id, r.set_reloid
+ FROM pglogical.replication_set_relation r;
+
+ELSE
+ RAISE EXCEPTION 'No table pglogical.replication_set_relation or pglogical.replication_set_table found';
+END IF;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deployment_check_wrapper(p_set_config_id integer, p_set_name text)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+ v_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_set_config_id INT;
+ c_include_schema_regex TEXT;
+ v_include_only_repset_tables BOOLEAN;
+ v_ddl_only_replication BOOLEAN;
+ c_set_name TEXT;
+BEGIN
+
+IF p_set_config_id IS NOT NULL AND p_set_name IS NOT NULL THEN
+ RAISE EXCEPTION 'This function can only be called with one of the two arguments set.';
+END IF;
+
+IF NOT EXISTS (SELECT 1 FROM pgl_ddl_deploy.set_configs WHERE ((p_set_name is null and id = p_set_config_id) OR (p_set_config_id is null and set_name = p_set_name))) THEN
+ RETURN FALSE;
+END IF;
+
+/***
+ This check is only applicable to NON-include_only_repset_tables and sets using CREATE TABLE events.
+ It is also bypassed if ddl_only_replication is true in which we never auto-add tables to replication.
+ We re-assign set_config_id because we want to know if no records are found, leading to NULL
+*/
+SELECT id, include_schema_regex, set_name, include_only_repset_tables, ddl_only_replication
+INTO c_set_config_id, c_include_schema_regex, c_set_name, v_include_only_repset_tables, v_ddl_only_replication
+FROM pgl_ddl_deploy.set_configs
+WHERE ((p_set_name is null and id = p_set_config_id)
+ OR (p_set_config_id is null and set_name = p_set_name))
+ AND create_tags && '{"CREATE TABLE"}'::TEXT[];
+
+IF v_include_only_repset_tables OR v_ddl_only_replication THEN
+ RETURN TRUE;
+END IF;
+
+RETURN pgl_ddl_deploy.deployment_check_count(c_set_config_id, c_set_name, c_include_schema_regex);
+
+END;
+$function$;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deployment_check(p_set_config_id integer)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+
+RETURN pgl_ddl_deploy.deployment_check_wrapper(p_set_config_id, NULL);
+
+END;
+$function$;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deployment_check(p_set_name text)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+
+RETURN pgl_ddl_deploy.deployment_check_wrapper(NULL, p_set_name);
+
+END;
+$function$;
+
+
+
+
+CREATE FUNCTION pgl_ddl_deploy.get_altertable_subcmdinfo(pg_ddl_command)
+ RETURNS text[] IMMUTABLE STRICT
+ AS '$libdir/ddl_deparse', 'get_altertable_subcmdinfo' LANGUAGE C;
+
+CREATE FUNCTION pgl_ddl_deploy.get_command_tag(pg_ddl_command)
+ RETURNS text IMMUTABLE STRICT
+ AS '$libdir/ddl_deparse', 'get_command_tag' LANGUAGE C;
+
+CREATE FUNCTION pgl_ddl_deploy.get_command_type(pg_ddl_command)
+ RETURNS text IMMUTABLE STRICT
+ AS '$libdir/ddl_deparse', 'get_command_type' LANGUAGE C;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.standard_repset_only_tags()
+ RETURNS text[]
+ LANGUAGE sql
+ IMMUTABLE
+AS $function$
+SELECT '{
+ "ALTER TABLE"
+ ,COMMENT}'::TEXT[];
+$function$
+;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.standard_create_tags()
+ RETURNS text[]
+ LANGUAGE sql
+ IMMUTABLE
+AS $function$
+SELECT '{
+ "ALTER TABLE"
+ ,"CREATE SEQUENCE"
+ ,"ALTER SEQUENCE"
+ ,"CREATE SCHEMA"
+ ,"CREATE TABLE"
+ ,"CREATE FUNCTION"
+ ,"ALTER FUNCTION"
+ ,"CREATE TYPE"
+ ,"ALTER TYPE"
+ ,"CREATE VIEW"
+ ,"ALTER VIEW"
+ ,COMMENT}'::TEXT[];
+$function$
+;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.exclude_regex()
+ RETURNS text
+ LANGUAGE sql
+ IMMUTABLE
+AS $function$
+SELECT '^(pg_catalog|information_schema|pg_temp.*|pg_toast.*|pgl_ddl_deploy|pglogical|pglogical_ticker|repack)$'::TEXT;
+$function$
+;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.common_exclude_alter_table_subcommands()
+RETURNS TEXT[] AS
+$BODY$
+SELECT ARRAY[
+ 'ADD CONSTRAINT',
+ 'ADD CONSTRAINT (and recurse)',
+ '(re) ADD CONSTRAINT',
+ 'ALTER CONSTRAINT',
+ 'VALIDATE CONSTRAINT',
+ 'VALIDATE CONSTRAINT (and recurse)',
+ 'ADD (processed) CONSTRAINT',
+ 'ADD CONSTRAINT (using index)',
+ 'DROP CONSTRAINT',
+ 'DROP CONSTRAINT (and recurse)',
+ 'SET LOGGED',
+ 'SET UNLOGGED',
+ 'SET TABLESPACE',
+ 'SET RELOPTIONS',
+ 'RESET RELOPTIONS',
+ 'REPLACE RELOPTIONS',
+ 'ENABLE TRIGGER',
+ 'ENABLE TRIGGER (always)',
+ 'ENABLE TRIGGER (replica)',
+ 'DISABLE TRIGGER',
+ 'ENABLE TRIGGER (all)',
+ 'DISABLE TRIGGER (all)',
+ 'ENABLE TRIGGER (user)',
+ 'DISABLE TRIGGER (user)',
+ 'ENABLE RULE',
+ 'ENABLE RULE (always)',
+ 'ENABLE RULE (replica)',
+ 'DISABLE RULE',
+ 'SET OPTIONS']::TEXT[];
+$BODY$
+LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.unique_tags()
+ RETURNS trigger
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+ IF NOT NEW.ddl_only_replication AND EXISTS (
+ SELECT 1
+ FROM pgl_ddl_deploy.set_configs
+ WHERE id <> NEW.id
+ AND set_name = NEW.set_name
+ AND NOT NEW.ddl_only_replication
+ AND (create_tags && NEW.create_tags
+ OR drop_tags && NEW.drop_tags)) THEN
+ RAISE EXCEPTION $$Another set_config already exists for '%' with overlapping create_tags or drop_tags.
+ Command tags must only appear once per set_name even if using multiple set_configs, unless you
+ are using the ddl_only_replication setting.
+ $$, NEW.set_name;
+ END IF;
+ RETURN NEW;
+END;
+$function$
+;
+
+
+ALTER TABLE pgl_ddl_deploy.set_configs ADD CONSTRAINT repset_tables_restricted_tags CHECK ((NOT include_only_repset_tables) OR (include_only_repset_tables AND pgl_ddl_deploy.standard_repset_only_tags() @> create_tags AND drop_tags IS NULL));
+
+
+
+/* pgl_ddl_deploy--1.4--1.5.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+ALTER TABLE pgl_ddl_deploy.set_configs
+ ADD COLUMN include_everything
+ BOOLEAN NOT NULL DEFAULT FALSE;
+
+-- Now we have 3 configuration types
+ALTER TABLE pgl_ddl_deploy.set_configs
+ DROP CONSTRAINT repset_tables_or_regex_inclusion;
+
+-- Only allow one of them to be chosen
+ALTER TABLE pgl_ddl_deploy.set_configs
+ ADD CONSTRAINT single_configuration_type
+ CHECK
+ ((include_schema_regex IS NOT NULL
+ AND NOT include_only_repset_tables)
+ OR
+ (include_only_repset_tables
+ AND include_schema_regex IS NULL)
+ OR
+ (include_everything
+ AND NOT include_only_repset_tables
+ AND include_schema_regex IS NULL));
+
+ALTER TABLE pgl_ddl_deploy.set_configs
+ ADD CONSTRAINT ddl_only_restrictions
+ CHECK (NOT (ddl_only_replication AND include_only_repset_tables));
+
+-- Need to adjust to after trigger and change function def
+DROP TRIGGER unique_tags ON pgl_ddl_deploy.set_configs;
+DROP FUNCTION pgl_ddl_deploy.unique_tags();
+
+
+-- Support canceling or terminating blocking processes on subscriber
+CREATE TYPE pgl_ddl_deploy.signals AS ENUM ('cancel','terminate','cancel_then_terminate');
+ALTER TABLE pgl_ddl_deploy.set_configs
+ ADD COLUMN signal_blocking_subscriber_sessions pgl_ddl_deploy.signals;
+ALTER TABLE pgl_ddl_deploy.set_configs
+ ADD COLUMN subscriber_lock_timeout INT;
+
+ALTER TABLE pgl_ddl_deploy.set_configs
+ ADD CONSTRAINT valid_signal_blocker_config
+ CHECK
+ (NOT (lock_safe_deployment AND (signal_blocking_subscriber_sessions IS NOT NULL OR subscriber_lock_timeout IS NOT NULL))
+ AND NOT (subscriber_lock_timeout IS NOT NULL AND signal_blocking_subscriber_sessions IS NULL));
+
+CREATE TABLE pgl_ddl_deploy.killed_blockers
+(
+ id SERIAL PRIMARY KEY,
+ signal TEXT,
+ successful BOOLEAN,
+ pid INT,
+ executed_at TIMESTAMPTZ,
+ usename NAME,
+ client_addr INET,
+ xact_start TIMESTAMPTZ,
+ state_change TIMESTAMPTZ,
+ state TEXT,
+ query TEXT,
+ reported BOOLEAN DEFAULT FALSE,
+ reported_at TIMESTAMPTZ
+);
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.unique_tags()
+ RETURNS trigger
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+ v_output TEXT;
+BEGIN
+ WITH dupes AS (
+ SELECT set_name,
+ CASE
+ WHEN include_only_repset_tables THEN 'include_only_repset_tables'
+ WHEN include_everything AND NOT ddl_only_replication THEN 'include_everything'
+ WHEN include_schema_regex IS NOT NULL AND NOT ddl_only_replication THEN 'include_schema_regex'
+ WHEN ddl_only_replication THEN
+ CASE
+ WHEN include_everything THEN 'ddl_only_include_everything'
+ WHEN include_schema_regex IS NOT NULL THEN 'ddl_only_include_schema_regex'
+ END
+ END AS category,
+ unnest(array_cat(create_tags, drop_tags)) AS command_tag
+ FROM pgl_ddl_deploy.set_configs
+ GROUP BY 1, 2, 3
+ HAVING COUNT(1) > 1)
+
+ , aggregate_dupe_tags AS (
+ SELECT set_name, category, string_agg(command_tag, ', ' ORDER BY command_tag) AS command_tags
+ FROM dupes
+ GROUP BY 1, 2
+ )
+
+ SELECT string_agg(format('%s: %s: %s', set_name, category, command_tags), ', ') AS output
+ INTO v_output
+ FROM aggregate_dupe_tags;
+
+ IF v_output IS NOT NULL THEN
+ RAISE EXCEPTION '%', format('You have overlapping configuration types and command tags which is not permitted: %s', v_output);
+ END IF;
+ RETURN NULL;
+END;
+$function$
+;
+
+
+CREATE TRIGGER unique_tags
+AFTER INSERT OR UPDATE ON pgl_ddl_deploy.set_configs
+FOR EACH ROW EXECUTE PROCEDURE pgl_ddl_deploy.unique_tags();
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.kill_blockers
+(p_signal pgl_ddl_deploy.signals,
+p_nspname NAME,
+p_relname NAME)
+RETURNS TABLE (
+signal pgl_ddl_deploy.signals,
+successful BOOLEAN,
+raised_message BOOLEAN,
+pid INT,
+executed_at TIMESTAMPTZ,
+usename NAME,
+client_addr INET,
+xact_start TIMESTAMPTZ,
+state_change TIMESTAMPTZ,
+state TEXT,
+query TEXT,
+reported BOOLEAN
+)
+AS
+$BODY$
+/****
+This function is only called on the subscriber on which we are applying DDL,
+when it is blocked and hits the configured lock_timeout.
+
+It is called by the function pgl_ddl_deploy.subscriber_command() only if it hits
+lock_timeout and it is configured to send a signal to blocking queries.
+
+It has three main features:
+ 1. Signal blocking sessions with either cancel or terminate.
+ 2. Raise a WARNING message to server logs in case of a kill attempt
+ 3. Return the recordset with details of killed queries for auditing purposes.
+****/
+BEGIN
+
+RETURN QUERY
+SELECT p_signal AS signal,
+ CASE
+ WHEN p_signal IS NULL
+ THEN FALSE
+ WHEN p_signal = 'cancel'
+ THEN pg_cancel_backend(l.pid)
+ WHEN p_signal = 'terminate'
+ THEN pg_terminate_backend(l.pid)
+ END AS successful,
+ CASE
+ WHEN p_signal IS NULL
+ THEN FALSE
+ WHEN p_signal = 'cancel'
+ THEN pgl_ddl_deploy.raise_message('WARNING', format('Attempting cancel of blocking pid %s, query: %s', l.pid, a.query))
+ WHEN p_signal = 'terminate'
+ THEN pgl_ddl_deploy.raise_message('WARNING', format('Attempting termination of blocking pid %s, query: %s', l.pid, a.query))
+ END AS raised_message,
+ l.pid,
+ now() AS executed_at,
+ a.usename,
+ a.client_addr,
+ a.xact_start,
+ a.state_change,
+ a.state,
+ a.query,
+ FALSE AS reported
+FROM pg_locks l
+INNER JOIN pg_class c on l.relation = c.oid
+INNER JOIN pg_namespace n on c.relnamespace = n.oid
+INNER JOIN pg_stat_activity a on l.pid = a.pid
+-- We do not exclude either postgres user or pglogical processes, because we even want to cancel autovac blocks.
+-- It should not be possible to contend with pglogical write processes (at least as of pglogical 2.2), because
+-- these run single-threaded using the same process that is doing the DDL and already holds any lock it needs
+-- on the target table.
+WHERE NOT a.pid = pg_backend_pid()
+-- both nspname and relname will be an empty string, thus a no-op, if for some reason one or the other
+-- is not found on the provider side in pg_event_trigger_ddl_commands(). This is a safety mechanism!
+AND n.nspname = p_nspname
+AND c.relname = p_relname
+AND a.datname = current_database()
+AND c.relkind = 'r'
+AND l.locktype = 'relation'
+ORDER BY a.state_change DESC;
+
+END;
+$BODY$
+SECURITY DEFINER
+LANGUAGE plpgsql VOLATILE;
+
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.kill_blockers(pgl_ddl_deploy.signals, NAME, NAME) FROM PUBLIC;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.add_role(p_roleoid oid)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+/******
+Assuming roles doing DDL are not superusers, this function grants needed privileges
+to run through the pgl_ddl_deploy DDL deployment.
+This needs to be run on BOTH provider and subscriber.
+******/
+DECLARE
+ v_rec RECORD;
+ v_sql TEXT;
+BEGIN
+
+ FOR v_rec IN
+ SELECT quote_ident(rolname) AS rolname FROM pg_roles WHERE oid = p_roleoid
+ LOOP
+
+ v_sql:='
+ GRANT USAGE ON SCHEMA pglogical TO '||v_rec.rolname||';
+ GRANT USAGE ON SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pglogical.replicate_ddl_command(text, text[]) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pglogical.replication_set_add_table(name, regclass, boolean, text[], text) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.sql_command_tags(text) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.kill_blockers(pgl_ddl_deploy.signals, name, name) TO '||v_rec.rolname||';
+ GRANT INSERT, UPDATE, SELECT ON ALL TABLES IN SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';
+ GRANT USAGE ON ALL SEQUENCES IN SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';
+ GRANT SELECT ON ALL TABLES IN SCHEMA pglogical TO '||v_rec.rolname||';';
+
+ EXECUTE v_sql;
+ RETURN true;
+ END LOOP;
+RETURN false;
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.subscriber_command
+(
+ p_provider_name NAME,
+ p_set_name TEXT[],
+ p_nspname NAME,
+ p_relname NAME,
+ p_ddl_sql_sent TEXT,
+ p_full_ddl TEXT,
+ p_pid INT,
+ p_set_config_id INT,
+ p_queue_subscriber_failures BOOLEAN,
+ p_signal_blocking_subscriber_sessions pgl_ddl_deploy.signals,
+ p_lock_timeout INT,
+-- This parameter currently only exists to make testing this function easier
+ p_run_anywhere BOOLEAN = FALSE
+)
+RETURNS BOOLEAN
+AS $pgl_ddl_deploy_sql$
+/****
+This function is what will actually be executed on the subscriber when attempting to apply DDL
+changed. It is sent to subscriber(s) via pglogical.replicate_ddl_command. You can see how it
+is called based on the the view pgl_ddl_deploy.event_trigger_schema, which is used to create the
+specific event trigger functions that will call this function in different ways depending on
+configuration in pgl_ddl_deploy.set_configs.
+
+This function is also used to make testing easier. The regression suite calls
+this function to verify basic functionality.
+****/
+DECLARE
+ v_succeeded BOOLEAN;
+ v_error_message TEXT;
+ v_attempt_number INT = 0;
+ v_signal pgl_ddl_deploy.signals;
+BEGIN
+
+--Only run on subscriber with this replication set, and matching provider node name
+IF EXISTS (SELECT 1
+ FROM pglogical.subscription s
+ INNER JOIN pglogical.node n
+ ON n.node_id = s.sub_origin
+ AND n.node_name = p_provider_name
+ WHERE sub_replication_sets && p_set_name) OR p_run_anywhere THEN
+
+ v_error_message = NULL;
+ /****
+ If we have configured to kill blocking subscribers, here we set parameters for that:
+ 1. Whether to cancel or terminate
+ 2. What lock_timeout to tolerate
+ ****/
+ IF p_signal_blocking_subscriber_sessions IS NOT NULL THEN
+ v_signal = CASE WHEN p_signal_blocking_subscriber_sessions = 'cancel_then_terminate' THEN 'cancel' ELSE p_signal_blocking_subscriber_sessions END;
+ -- We cannot RESET LOCAL lock_timeout but that should not be necessary because it will end with the transaction
+ EXECUTE format('SET LOCAL lock_timeout TO %s', p_lock_timeout);
+ END IF;
+
+ /****
+ Loop until one of the following takes place:
+ 1. Successful DDL execution on first attempt
+ 2. An unexpected ERROR occurs, which will either RAISE or finish with WARNING based on queue_subscriber_failures configuration
+ 3. Blocking sessions are killed until we finally get a successful DDL execution
+ ****/
+ WHILE TRUE LOOP
+ BEGIN
+
+ --Execute DDL
+ RAISE LOG 'pgl_ddl_deploy attempting execution: %', p_full_ddl;
+
+ --Execute DDL - the reason we use execute here is partly to handle no trailing semicolon
+ EXECUTE p_full_ddl;
+
+ v_succeeded = TRUE;
+ EXIT;
+
+ EXCEPTION
+ WHEN lock_not_available THEN
+ IF p_signal_blocking_subscriber_sessions IS NOT NULL THEN
+ -- Change to terminate if we are using cancel_then_terminate and have not been successful after the first iteration
+ IF v_attempt_number > 0 AND p_signal_blocking_subscriber_sessions = 'cancel_then_terminate' AND v_signal = 'cancel' THEN
+ v_signal = 'terminate';
+ END IF;
+ INSERT INTO pgl_ddl_deploy.killed_blockers
+ (signal,
+ successful,
+ pid,
+ executed_at,
+ usename,
+ client_addr,
+ xact_start,
+ state_change,
+ state,
+ query,
+ reported)
+ SELECT
+ signal,
+ successful,
+ pid,
+ executed_at,
+ usename,
+ client_addr,
+ xact_start,
+ state_change,
+ state,
+ query,
+ reported
+ FROM pgl_ddl_deploy.kill_blockers(
+ v_signal,
+ p_nspname,
+ p_relname
+ );
+
+ -- Continue and retry again but allow a brief pause
+ v_attempt_number = v_attempt_number + 1;
+ PERFORM pg_sleep(3);
+ ELSE
+ -- If p_signal_blocking_subscriber_sessions is not configured but we hit a lock_timeout,
+ -- then the replication user or cluster is configured with a global lock_timeout. Raise in this case.
+ RAISE;
+ END IF;
+ WHEN OTHERS THEN
+ IF p_queue_subscriber_failures THEN
+ RAISE WARNING 'Subscriber DDL failed with errors (see pgl_ddl_deploy.subscriber_logs): %', SQLERRM;
+ v_succeeded = FALSE;
+ v_error_message = SQLERRM;
+ EXIT;
+ ELSE
+ RAISE;
+ END IF;
+ END;
+ END LOOP;
+
+ /****
+ Since this function is only executed on the subscriber, this INSERT adds a log
+ to subscriber_logs on the subscriber after execution.
+
+ Note that if we configured queue_subscriber_failures to TRUE in pgl_ddl_deploy.set_configs, then we are
+ allowing failed DDL to be caught and logged in this table as succeeded = FALSE for later processing.
+ ****/
+ INSERT INTO pgl_ddl_deploy.subscriber_logs
+ (set_name,
+ provider_pid,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ subscriber_pid,
+ executed_at,
+ ddl_sql,
+ full_ddl_sql,
+ succeeded,
+ error_message)
+ VALUES
+ (p_set_name,
+ p_pid,
+ p_provider_name,
+ p_set_config_id,
+ current_role,
+ pg_backend_pid(),
+ current_timestamp,
+ p_ddl_sql_sent,
+ p_full_ddl,
+ v_succeeded,
+ v_error_message);
+
+END IF;
+
+RETURN v_succeeded;
+
+END;
+$pgl_ddl_deploy_sql$
+LANGUAGE plpgsql VOLATILE;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.raise_message
+(p_log_level TEXT,
+p_message TEXT)
+RETURNS BOOLEAN
+AS $BODY$
+BEGIN
+
+EXECUTE format($$
+DO $block$
+BEGIN
+RAISE %s $pgl_ddl_deploy_msg$%s$pgl_ddl_deploy_msg$;
+END$block$;
+$$, p_log_level, p_message);
+RETURN TRUE;
+
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.blacklisted_tags()
+ RETURNS text[]
+ LANGUAGE sql
+ IMMUTABLE
+AS $function$
+SELECT '{
+ INSERT,
+ UPDATE,
+ DELETE,
+ TRUNCATE,
+ ROLLBACK,
+ "CREATE EXTENSION",
+ "ALTER EXTENSION",
+ "DROP EXTENSION"}'::TEXT[];
+$function$
+;
+
+
+
+
+-- Ensure added roles have write permissions for new tables added
+-- Not so easy to pre-package this with default privileges because
+-- we can't assume everyone uses the same role to deploy this extension
+SELECT pgl_ddl_deploy.add_role(role_oid)
+FROM (
+SELECT DISTINCT r.oid AS role_oid
+FROM information_schema.table_privileges tp
+INNER JOIN pg_roles r ON r.rolname = tp.grantee AND NOT r.rolsuper
+WHERE table_schema = 'pgl_ddl_deploy'
+ AND privilege_type = 'INSERT'
+ AND table_name = 'subscriber_logs'
+) roles_with_existing_privileges;
+
+
+/* pgl_ddl_deploy--1.5--1.6.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+CREATE FUNCTION pgl_ddl_deploy.current_query()
+RETURNS TEXT AS
+'MODULE_PATHNAME', 'pgl_ddl_deploy_current_query'
+LANGUAGE C VOLATILE STRICT;
+
+-- Drop UPDATE event for this trigger, which leads to unexpected behavior
+DROP TRIGGER set_tag_defaults ON pgl_ddl_deploy.set_configs;
+CREATE TRIGGER set_tag_defaults
+BEFORE INSERT ON pgl_ddl_deploy.set_configs
+FOR EACH ROW EXECUTE PROCEDURE pgl_ddl_deploy.set_tag_defaults();
+
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.kill_blockers
+(p_signal pgl_ddl_deploy.signals,
+p_nspname NAME,
+p_relname NAME)
+RETURNS TABLE (
+signal pgl_ddl_deploy.signals,
+successful BOOLEAN,
+raised_message BOOLEAN,
+pid INT,
+executed_at TIMESTAMPTZ,
+usename NAME,
+client_addr INET,
+xact_start TIMESTAMPTZ,
+state_change TIMESTAMPTZ,
+state TEXT,
+query TEXT,
+reported BOOLEAN
+)
+AS
+$BODY$
+/****
+This function is only called on the subscriber on which we are applying DDL,
+when it is blocked and hits the configured lock_timeout.
+
+It is called by the function pgl_ddl_deploy.subscriber_command() only if it hits
+lock_timeout and it is configured to send a signal to blocking queries.
+
+It has three main features:
+ 1. Signal blocking sessions with either cancel or terminate.
+ 2. Raise a WARNING message to server logs in case of a kill attempt
+ 3. Return the recordset with details of killed queries for auditing purposes.
+****/
+BEGIN
+
+RETURN QUERY
+SELECT DISTINCT ON (l.pid)
+ p_signal AS signal,
+ CASE
+ WHEN p_signal IS NULL
+ THEN FALSE
+ WHEN p_signal = 'cancel'
+ THEN pg_cancel_backend(l.pid)
+ WHEN p_signal = 'terminate'
+ THEN pg_terminate_backend(l.pid)
+ END AS successful,
+ CASE
+ WHEN p_signal IS NULL
+ THEN FALSE
+ WHEN p_signal = 'cancel'
+ THEN pgl_ddl_deploy.raise_message('WARNING', format('Attempting cancel of blocking pid %s, query: %s', l.pid, a.query))
+ WHEN p_signal = 'terminate'
+ THEN pgl_ddl_deploy.raise_message('WARNING', format('Attempting termination of blocking pid %s, query: %s', l.pid, a.query))
+ END AS raised_message,
+ l.pid,
+ now() AS executed_at,
+ a.usename,
+ a.client_addr,
+ a.xact_start,
+ a.state_change,
+ a.state,
+ a.query,
+ FALSE AS reported
+FROM pg_locks l
+INNER JOIN pg_class c on l.relation = c.oid
+INNER JOIN pg_namespace n on c.relnamespace = n.oid
+INNER JOIN pg_stat_activity a on l.pid = a.pid
+/***
+ We need to check if this is an inheritance parent,
+ because even a share lock on a child will prevent DDL on parent
+***/
+LEFT JOIN pg_inherits pi ON pi.inhrelid = c.oid
+LEFT JOIN pg_class ipc on ipc.oid = pi.inhparent
+LEFT JOIN pg_namespace ipn on ipn.oid = ipc.relnamespace
+-- We do not exclude either postgres user or pglogical processes, because we even want to cancel autovac blocks.
+-- It should not be possible to contend with pglogical write processes (at least as of pglogical 2.2), because
+-- these run single-threaded using the same process that is doing the DDL and already holds any lock it needs
+-- on the target table.
+WHERE NOT a.pid = pg_backend_pid()
+-- both nspname and relname will be an empty string, thus a no-op, if for some reason one or the other
+-- is not found on the provider side in pg_event_trigger_ddl_commands(). This is a safety mechanism!
+AND ((n.nspname = p_nspname AND c.relname = p_relname)
+OR (ipn.nspname = p_nspname AND ipc.relname = p_relname))
+AND a.datname = current_database()
+AND c.relkind = 'r'
+AND l.locktype = 'relation'
+ORDER BY l.pid, a.state_change DESC;
+
+END;
+$BODY$
+SECURITY DEFINER
+LANGUAGE plpgsql VOLATILE;
+
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.kill_blockers(pgl_ddl_deploy.signals, NAME, NAME) FROM PUBLIC;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.raise_message
+(p_log_level TEXT,
+p_message TEXT)
+RETURNS BOOLEAN
+AS $BODY$
+BEGIN
+
+EXECUTE format($$
+DO $block$
+BEGIN
+RAISE %s $pgl_ddl_deploy_msg$%s$pgl_ddl_deploy_msg$;
+END$block$;
+$$, p_log_level, REPLACE(p_message,'%','%%'));
+RETURN TRUE;
+
+END;
+$BODY$
+LANGUAGE plpgsql VOLATILE;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.standard_create_tags()
+ RETURNS text[]
+ LANGUAGE sql
+ IMMUTABLE
+AS $function$
+SELECT '{
+ "ALTER TABLE"
+ ,"CREATE SEQUENCE"
+ ,"ALTER SEQUENCE"
+ ,"CREATE SCHEMA"
+ ,"CREATE TABLE"
+ ,"CREATE FUNCTION"
+ ,"ALTER FUNCTION"
+ ,"CREATE TYPE"
+ ,"ALTER TYPE"
+ ,"CREATE VIEW"
+ ,"ALTER VIEW"
+ ,COMMENT
+ ,"CREATE RULE"
+ ,"CREATE TRIGGER"
+ ,"ALTER TRIGGER"}'::TEXT[];
+$function$
+;
+
+
+
+
+/* pgl_ddl_deploy--1.6--1.7.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.add_role(p_roleoid oid)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+/******
+Assuming roles doing DDL are not superusers, this function grants needed privileges
+to run through the pgl_ddl_deploy DDL deployment.
+This needs to be run on BOTH provider and subscriber.
+******/
+DECLARE
+ v_rec RECORD;
+ v_sql TEXT;
+ v_rsat_args TEXT;
+BEGIN
+
+ FOR v_rec IN
+ SELECT quote_ident(rolname) AS rolname FROM pg_roles WHERE oid = p_roleoid
+ LOOP
+
+ v_rsat_args:=pg_get_function_identity_arguments('pglogical.replication_set_add_table'::REGPROC);
+
+
+ v_sql:='
+ GRANT USAGE ON SCHEMA pglogical TO '||v_rec.rolname||';
+ GRANT USAGE ON SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pglogical.replicate_ddl_command(text, text[]) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pglogical.replication_set_add_table(' || v_rsat_args || ') TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.sql_command_tags(text) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.kill_blockers(pgl_ddl_deploy.signals, name, name) TO '||v_rec.rolname||';
+ GRANT INSERT, UPDATE, SELECT ON ALL TABLES IN SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';
+ GRANT USAGE ON ALL SEQUENCES IN SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';
+ GRANT SELECT ON ALL TABLES IN SCHEMA pglogical TO '||v_rec.rolname||';';
+
+
+
+
+ EXECUTE v_sql;
+ RETURN true;
+ END LOOP;
+RETURN false;
+END;
+$function$
+;
+
+
+/* pgl_ddl_deploy--1.7--2.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+/*
+ * We need to re-deploy the trigger function definitions
+ * which will have changed with this extension update. So
+ * here we undeploy them, and save which ones we need to
+ * recreate later.
+*/
+DO $$
+BEGIN
+
+IF EXISTS (SELECT 1 FROM pg_views WHERE schemaname = 'pgl_ddl_deploy' AND viewname = 'event_trigger_schema') THEN
+
+DROP TABLE IF EXISTS ddl_deploy_to_refresh;
+CREATE TEMP TABLE ddl_deploy_to_refresh AS
+SELECT id, pgl_ddl_deploy.undeploy(id) AS undeployed
+FROM pgl_ddl_deploy.event_trigger_schema
+WHERE is_deployed;
+
+ELSE
+
+DROP TABLE IF EXISTS ddl_deploy_to_refresh;
+CREATE TEMP TABLE ddl_deploy_to_refresh AS
+SELECT NULL::INT AS id;
+
+END IF;
+END$$;
+
+CREATE TYPE pgl_ddl_deploy.driver AS ENUM ('pglogical', 'native');
+-- Not possible that any existing config would be native, so:
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN driver pgl_ddl_deploy.driver NOT NULL DEFAULT 'pglogical';
+DROP FUNCTION IF EXISTS pgl_ddl_deploy.rep_set_table_wrapper();
+DROP FUNCTION IF EXISTS pgl_ddl_deploy.deployment_check_count(integer, text, text);
+DROP FUNCTION pgl_ddl_deploy.subscriber_command
+(
+ p_provider_name NAME,
+ p_set_name TEXT[],
+ p_nspname NAME,
+ p_relname NAME,
+ p_ddl_sql_sent TEXT,
+ p_full_ddl TEXT,
+ p_pid INT,
+ p_set_config_id INT,
+ p_queue_subscriber_failures BOOLEAN,
+ p_signal_blocking_subscriber_sessions pgl_ddl_deploy.signals,
+ p_lock_timeout INT,
+-- This parameter currently only exists to make testing this function easier
+ p_run_anywhere BOOLEAN
+);
+
+CREATE TABLE pgl_ddl_deploy.queue(
+queued_at timestamp with time zone not null,
+role name not null,
+pubnames text[],
+message_type "char" not null,
+message text not null
+);
+COMMENT ON TABLE pgl_ddl_deploy.queue IS 'Modeled on the pglogical.queue table for native logical replication ddl';
+ALTER TABLE pgl_ddl_deploy.queue REPLICA IDENTITY FULL;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.override() RETURNS BOOLEAN AS $BODY$
+BEGIN
+RETURN FALSE;
+END;
+$BODY$
+LANGUAGE plpgsql IMMUTABLE;
+
+-- NOTE - this duplicates execute_queued_ddl.sql function file but is executed here for the upgrade/build path
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.execute_queued_ddl()
+ RETURNS trigger
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+
+/***
+Native logical replication does not support row filtering, so as a result,
+we need to do processing downstream to ensure we only process rows we care about.
+
+For example, if we propagate some DDL to system 1 and some other to system 2,
+all rows will still come through this trigger. We filter out rows based on
+matching pubnames with pg_subscription.subpublications
+
+If a row arrives here (the subscriber), it must mean that it was propagated
+***/
+
+IF NEW.message_type = pgl_ddl_deploy.queue_ddl_message_type() AND
+ (pgl_ddl_deploy.override() OR ((SELECT COUNT(1) FROM pg_subscription s
+ WHERE subpublications && NEW.pubnames) > 0)) THEN
+
+ -- See https://www.postgresql.org/message-id/CAMa1XUh7ZVnBzORqjJKYOv4_pDSDUCvELRbkF0VtW7pvDW9rZw@mail.gmail.com
+ IF NEW.message ~* 'pgl_ddl_deploy.notify_subscription_refresh' THEN
+ INSERT INTO pgl_ddl_deploy.subscriber_logs
+ (set_name,
+ provider_pid,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ subscriber_pid,
+ executed_at,
+ ddl_sql,
+ full_ddl_sql,
+ succeeded,
+ error_message)
+ VALUES
+ (NEW.pubnames[1],
+ NULL,
+ NULL,
+ NULL,
+ current_role,
+ pg_backend_pid(),
+ current_timestamp,
+ NEW.message,
+ NEW.message,
+ FALSE,
+ 'Unsupported automated ALTER SUBSCRIPTION ... REFRESH PUBLICATION until bugfix');
+ ELSE
+ EXECUTE 'SET ROLE '||quote_ident(NEW.role)||';';
+ EXECUTE NEW.message::TEXT;
+ END IF;
+
+ RETURN NEW;
+ELSE
+ RETURN NULL;
+END IF;
+
+END;
+$function$
+;
+
+CREATE TRIGGER execute_queued_ddl
+BEFORE INSERT ON pgl_ddl_deploy.queue
+FOR EACH ROW EXECUTE PROCEDURE pgl_ddl_deploy.execute_queued_ddl();
+
+-- This must only fire on the replica
+ALTER TABLE pgl_ddl_deploy.queue ENABLE REPLICA TRIGGER execute_queued_ddl;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.replicate_ddl_command(command text, pubnames text[])
+ RETURNS BOOLEAN
+ LANGUAGE plpgsql
+AS $function$
+-- Modeled after pglogical's replicate_ddl_command but in support of native logical replication
+BEGIN
+
+-- NOTE: pglogical uses clock_timestamp() to log queued_at times and we do the same here
+INSERT INTO pgl_ddl_deploy.queue (queued_at, role, pubnames, message_type, message)
+VALUES (clock_timestamp(), current_role, pubnames, pgl_ddl_deploy.queue_ddl_message_type(), command);
+
+RETURN TRUE;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.add_table_to_replication(p_driver pgl_ddl_deploy.driver, p_set_name name, p_relation regclass, p_synchronize_data boolean DEFAULT false)
+ RETURNS BOOLEAN
+ LANGUAGE plpgsql
+ SECURITY DEFINER
+AS $function$
+DECLARE
+ v_schema NAME;
+ v_table NAME;
+ v_result BOOLEAN = false;
+BEGIN
+IF p_driver = 'pglogical' THEN
+
+ SELECT pglogical.replication_set_add_table(
+ set_name:=p_set_name
+ ,relation:=p_relation
+ ,synchronize_data:=p_synchronize_data
+ ) INTO v_result;
+
+ELSEIF p_driver = 'native' THEN
+
+ SELECT nspname, relname INTO v_schema, v_table
+ FROM pg_class c
+ JOIN pg_namespace n ON n.oid = c.relnamespace
+ WHERE c.oid = p_relation::OID;
+
+ EXECUTE 'ALTER PUBLICATION '||quote_ident(p_set_name)||' ADD TABLE '||quote_ident(v_schema)||'.'||quote_ident(v_table)||';';
+
+ -- We use true to synchronize data here, not taking the value from p_synchronize_data. This is because of the different way
+ -- that native logical works, and that changes are not queued from the time of the table being added to replication. Thus, we
+ -- by default WILL use COPY_DATA = true
+
+ -- This needs to be in a DO block currently because of how the DDL is processed on the subscriber.
+ PERFORM pgl_ddl_deploy.replicate_ddl_command($$DO $AUTO_REPLICATE_BLOCK$
+ BEGIN
+ PERFORM pgl_ddl_deploy.notify_subscription_refresh('$$||p_set_name||$$', true);
+ END$AUTO_REPLICATE_BLOCK$;$$, array[p_set_name]);
+ v_result = true;
+
+ELSE
+
+RAISE EXCEPTION 'Unsupported driver specified';
+
+END IF;
+
+RETURN v_result;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.notify_subscription_refresh(p_set_name name, p_copy_data boolean DEFAULT TRUE)
+ RETURNS BOOLEAN
+ LANGUAGE plpgsql
+ SECURITY DEFINER
+AS $function$
+DECLARE
+ v_rec RECORD;
+ v_sql TEXT;
+BEGIN
+
+ IF NOT EXISTS (SELECT 1 FROM pg_subscription WHERE subpublications && array[p_set_name::text]) THEN
+ RAISE EXCEPTION 'No subscription to publication % exists', p_set_name;
+ END IF;
+
+ FOR v_rec IN
+ SELECT unnest(subpublications) AS pubname, subname
+ FROM pg_subscription
+ WHERE subpublications && array[p_set_name::text]
+ LOOP
+
+ v_sql = $$ALTER SUBSCRIPTION $$||quote_ident(v_rec.subname)||$$ REFRESH PUBLICATION WITH ( COPY_DATA = '$$||p_copy_data||$$');$$;
+ RAISE LOG 'pgl_ddl_deploy executing: %', v_sql;
+ EXECUTE v_sql;
+
+ END LOOP;
+
+RETURN TRUE;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.rep_set_table_wrapper()
+ RETURNS TABLE (id OID, relid REGCLASS, name NAME, driver pgl_ddl_deploy.driver)
+ LANGUAGE plpgsql
+ SECURITY DEFINER
+AS $function$
+/*****
+This handles the rename of pglogical.replication_set_relation to pglogical.replication_set_table from version 1 to 2
+ */
+BEGIN
+
+IF current_setting('server_version_num')::INT < 100000 THEN
+ IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'pglogical' AND tablename = 'replication_set_table') THEN
+ RETURN QUERY
+ SELECT r.set_id AS id, r.set_reloid AS relid, rs.set_name AS name, 'pglogical'::pgl_ddl_deploy.driver AS driver
+ FROM pglogical.replication_set_table r
+ JOIN pglogical.replication_set rs USING (set_id);
+
+ ELSEIF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'pglogical' AND tablename = 'replication_set_relation') THEN
+ RETURN QUERY
+ SELECT r.set_id AS id, r.set_reloid AS relid, rs.set_name AS name, 'pglogical'::pgl_ddl_deploy.driver AS driver
+ FROM pglogical.replication_set_relation r
+ JOIN pglogical.replication_set rs USING (set_id);
+
+ ELSE
+ RAISE EXCEPTION 'No table pglogical.replication_set_relation or pglogical.replication_set_table found';
+ END IF;
+
+ELSE
+ IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pglogical') THEN
+ RETURN QUERY
+ SELECT p.oid AS id, prrelid::REGCLASS AS relid, pubname AS name, 'native'::pgl_ddl_deploy.driver AS driver
+ FROM pg_publication p
+ JOIN pg_publication_rel ppr ON ppr.prpubid = p.oid;
+
+ ELSEIF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'pglogical' AND tablename = 'replication_set_table') THEN
+ RETURN QUERY
+ SELECT r.set_id AS id, r.set_reloid AS relid, rs.set_name AS name, 'pglogical'::pgl_ddl_deploy.driver AS driver
+ FROM pglogical.replication_set_table r
+ JOIN pglogical.replication_set rs USING (set_id)
+ UNION ALL
+ SELECT p.oid AS id, prrelid::REGCLASS AS relid, pubname AS name, 'native'::pgl_ddl_deploy.driver AS driver
+ FROM pg_publication p
+ JOIN pg_publication_rel ppr ON ppr.prpubid = p.oid;
+
+ ELSEIF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'pglogical' AND tablename = 'replication_set_relation') THEN
+ RETURN QUERY
+ SELECT r.set_id AS id, r.set_reloid AS relid, rs.set_name AS name, 'pglogical'::pgl_ddl_deploy.driver AS driver
+ FROM pglogical.replication_set_relation r
+ JOIN pglogical.replication_set rs USING (set_id)
+ UNION ALL
+ SELECT p.oid AS id, prrelid::REGCLASS AS relid, pubname AS name, 'native'::pgl_ddl_deploy.driver AS driver
+ FROM pg_publication p
+ JOIN pg_publication_rel ppr ON ppr.prpubid = p.oid;
+ END IF;
+END IF;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.rep_set_wrapper()
+ RETURNS TABLE (id OID, name NAME, driver pgl_ddl_deploy.driver)
+ LANGUAGE plpgsql
+ SECURITY DEFINER
+AS $function$
+/*****
+This handles the rename of pglogical.replication_set_relation to pglogical.replication_set_table from version 1 to 2
+ */
+BEGIN
+
+IF current_setting('server_version_num')::INT < 100000 THEN
+ IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'pglogical') THEN
+ RETURN QUERY
+ SELECT set_id AS id, set_name AS name, 'pglogical'::pgl_ddl_deploy.driver AS driver
+ FROM pglogical.replication_set rs;
+
+ ELSE
+ RAISE EXCEPTION 'pglogical required for version prior to Postgres 10';
+ END IF;
+
+ELSE
+ IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pglogical') THEN
+ RETURN QUERY
+ SELECT p.oid AS id, pubname AS name, 'native'::pgl_ddl_deploy.driver AS driver
+ FROM pg_publication p;
+
+ ELSEIF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'pglogical') THEN
+ RETURN QUERY
+ SELECT set_id AS id, set_name AS name, 'pglogical'::pgl_ddl_deploy.driver AS driver
+ FROM pglogical.replication_set rs
+ UNION ALL
+ SELECT p.oid AS id, pubname AS name, 'native'::pgl_ddl_deploy.driver AS driver
+ FROM pg_publication p;
+ ELSE
+ RAISE EXCEPTION 'Unexpected exception';
+ END IF;
+
+
+END IF;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deployment_check_count(p_set_config_id integer, p_set_name text, p_include_schema_regex text, p_driver pgl_ddl_deploy.driver)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+ v_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+BEGIN
+
+--If the check is not applicable, pass it
+IF p_set_config_id IS NULL THEN
+ RETURN TRUE;
+END IF;
+
+SELECT COUNT(1)
+INTO v_count
+FROM pg_namespace n
+ INNER JOIN pg_class c ON n.oid = c.relnamespace
+ AND c.relpersistence = 'p'
+ WHERE n.nspname ~* p_include_schema_regex
+ AND n.nspname !~* c_exclude_always
+ AND EXISTS (SELECT 1
+ FROM pg_index i
+ WHERE i.indrelid = c.oid
+ AND i.indisprimary)
+ AND NOT EXISTS
+ (SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.name = p_set_name
+ AND rsr.relid = c.oid
+ AND rsr.driver = p_driver);
+
+IF v_count > 0 THEN
+ RAISE WARNING $ERR$
+ Deployment of auto-replication for id % set_name % failed
+ because % tables are already queued to be added to replication
+ based on your configuration. These tables need to be added to
+ replication manually and synced, otherwise change your configuration.
+ Debug query: %$ERR$,
+ p_set_config_id,
+ p_set_name,
+ v_count,
+ $SQL$
+ SELECT n.nspname, c.relname
+ FROM pg_namespace n
+ INNER JOIN pg_class c ON n.oid = c.relnamespace
+ AND c.relpersistence = 'p'
+ WHERE n.nspname ~* '$SQL$||p_include_schema_regex||$SQL$'
+ AND n.nspname !~* '$SQL$||c_exclude_always||$SQL$'
+ AND EXISTS (SELECT 1
+ FROM pg_index i
+ WHERE i.indrelid = c.oid
+ AND i.indisprimary)
+ AND NOT EXISTS
+ (SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.name = '$SQL$||p_set_name||$SQL$'
+ AND rsr.relid = c.oid
+ AND rsr.driver = (SELECT driver FROM pgl_ddl_deploy.set_configs WHERE set_name = '$SQL$||p_set_name||$SQL$'));
+ $SQL$;
+ RETURN FALSE;
+END IF;
+
+RETURN TRUE;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.deployment_check_wrapper(p_set_config_id integer, p_set_name text)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+ v_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_set_config_id INT;
+ c_include_schema_regex TEXT;
+ v_include_only_repset_tables BOOLEAN;
+ v_ddl_only_replication BOOLEAN;
+ c_set_name TEXT;
+ v_driver pgl_ddl_deploy.driver;
+BEGIN
+
+IF p_set_config_id IS NOT NULL AND p_set_name IS NOT NULL THEN
+ RAISE EXCEPTION 'This function can only be called with one of the two arguments set.';
+END IF;
+
+IF NOT EXISTS (SELECT 1 FROM pgl_ddl_deploy.set_configs WHERE ((p_set_name is null and id = p_set_config_id) OR (p_set_config_id is null and set_name = p_set_name))) THEN
+ RETURN FALSE;
+END IF;
+
+/***
+ This check is only applicable to NON-include_only_repset_tables and sets using CREATE TABLE events.
+ It is also bypassed if ddl_only_replication is true in which we never auto-add tables to replication.
+ We re-assign set_config_id because we want to know if no records are found, leading to NULL
+*/
+SELECT id, include_schema_regex, set_name, include_only_repset_tables, ddl_only_replication, driver
+INTO c_set_config_id, c_include_schema_regex, c_set_name, v_include_only_repset_tables, v_ddl_only_replication, v_driver
+FROM pgl_ddl_deploy.set_configs
+WHERE ((p_set_name is null and id = p_set_config_id)
+ OR (p_set_config_id is null and set_name = p_set_name))
+ AND create_tags && '{"CREATE TABLE"}'::TEXT[];
+
+IF v_include_only_repset_tables OR v_ddl_only_replication THEN
+ RETURN TRUE;
+END IF;
+
+RETURN pgl_ddl_deploy.deployment_check_count(c_set_config_id, c_set_name, c_include_schema_regex, v_driver);
+
+END;
+$function$;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.is_subscriber(p_driver pgl_ddl_deploy.driver, p_name TEXT[], p_provider_name NAME = NULL)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+
+IF p_driver = 'pglogical' THEN
+
+ RETURN EXISTS (SELECT 1
+ FROM pglogical.subscription s
+ INNER JOIN pglogical.node n
+ ON n.node_id = s.sub_origin
+ AND n.node_name = p_provider_name
+ WHERE sub_replication_sets && p_name);
+
+ELSEIF p_driver = 'native' THEN
+
+ RETURN EXISTS (SELECT 1
+ FROM pg_subscription s
+ WHERE subpublications && p_name);
+
+ELSE
+
+RAISE EXCEPTION 'Unsupported driver specified';
+
+END IF;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.subscriber_command
+(
+ p_provider_name NAME,
+ p_set_name TEXT[],
+ p_nspname NAME,
+ p_relname NAME,
+ p_ddl_sql_sent TEXT,
+ p_full_ddl TEXT,
+ p_pid INT,
+ p_set_config_id INT,
+ p_queue_subscriber_failures BOOLEAN,
+ p_signal_blocking_subscriber_sessions pgl_ddl_deploy.signals,
+ p_lock_timeout INT,
+ p_driver pgl_ddl_deploy.driver,
+-- This parameter currently only exists to make testing this function easier
+ p_run_anywhere BOOLEAN = FALSE
+)
+RETURNS BOOLEAN
+AS $pgl_ddl_deploy_sql$
+/****
+This function is what will actually be executed on the subscriber when attempting to apply DDL
+changed. It is sent to subscriber(s) via pglogical.replicate_ddl_command. You can see how it
+is called based on the the view pgl_ddl_deploy.event_trigger_schema, which is used to create the
+specific event trigger functions that will call this function in different ways depending on
+configuration in pgl_ddl_deploy.set_configs.
+
+This function is also used to make testing easier. The regression suite calls
+this function to verify basic functionality.
+****/
+DECLARE
+ v_succeeded BOOLEAN;
+ v_error_message TEXT;
+ v_attempt_number INT = 0;
+ v_signal pgl_ddl_deploy.signals;
+BEGIN
+
+IF pgl_ddl_deploy.is_subscriber(p_driver, p_set_name, p_provider_name) OR p_run_anywhere THEN
+
+ v_error_message = NULL;
+ /****
+ If we have configured to kill blocking subscribers, here we set parameters for that:
+ 1. Whether to cancel or terminate
+ 2. What lock_timeout to tolerate
+ ****/
+ IF p_signal_blocking_subscriber_sessions IS NOT NULL THEN
+ v_signal = CASE WHEN p_signal_blocking_subscriber_sessions = 'cancel_then_terminate' THEN 'cancel' ELSE p_signal_blocking_subscriber_sessions END;
+ -- We cannot RESET LOCAL lock_timeout but that should not be necessary because it will end with the transaction
+ EXECUTE format('SET LOCAL lock_timeout TO %s', p_lock_timeout);
+ END IF;
+
+ /****
+ Loop until one of the following takes place:
+ 1. Successful DDL execution on first attempt
+ 2. An unexpected ERROR occurs, which will either RAISE or finish with WARNING based on queue_subscriber_failures configuration
+ 3. Blocking sessions are killed until we finally get a successful DDL execution
+ ****/
+ WHILE TRUE LOOP
+ BEGIN
+
+ --Execute DDL
+ RAISE LOG 'pgl_ddl_deploy attempting execution: %', p_full_ddl;
+
+ --Execute DDL - the reason we use execute here is partly to handle no trailing semicolon
+ EXECUTE p_full_ddl;
+
+ v_succeeded = TRUE;
+ EXIT;
+
+ EXCEPTION
+ WHEN lock_not_available THEN
+ IF p_signal_blocking_subscriber_sessions IS NOT NULL THEN
+ -- Change to terminate if we are using cancel_then_terminate and have not been successful after the first iteration
+ IF v_attempt_number > 0 AND p_signal_blocking_subscriber_sessions = 'cancel_then_terminate' AND v_signal = 'cancel' THEN
+ v_signal = 'terminate';
+ END IF;
+ INSERT INTO pgl_ddl_deploy.killed_blockers
+ (signal,
+ successful,
+ pid,
+ executed_at,
+ usename,
+ client_addr,
+ xact_start,
+ state_change,
+ state,
+ query,
+ reported)
+ SELECT
+ signal,
+ successful,
+ pid,
+ executed_at,
+ usename,
+ client_addr,
+ xact_start,
+ state_change,
+ state,
+ query,
+ reported
+ FROM pgl_ddl_deploy.kill_blockers(
+ v_signal,
+ p_nspname,
+ p_relname
+ );
+
+ -- Continue and retry again but allow a brief pause
+ v_attempt_number = v_attempt_number + 1;
+ PERFORM pg_sleep(3);
+ ELSE
+ -- If p_signal_blocking_subscriber_sessions is not configured but we hit a lock_timeout,
+ -- then the replication user or cluster is configured with a global lock_timeout. Raise in this case.
+ RAISE;
+ END IF;
+ WHEN OTHERS THEN
+ IF p_queue_subscriber_failures THEN
+ RAISE WARNING 'Subscriber DDL failed with errors (see pgl_ddl_deploy.subscriber_logs): %', SQLERRM;
+ v_succeeded = FALSE;
+ v_error_message = SQLERRM;
+ EXIT;
+ ELSE
+ RAISE;
+ END IF;
+ END;
+ END LOOP;
+
+ /****
+ Since this function is only executed on the subscriber, this INSERT adds a log
+ to subscriber_logs on the subscriber after execution.
+
+ Note that if we configured queue_subscriber_failures to TRUE in pgl_ddl_deploy.set_configs, then we are
+ allowing failed DDL to be caught and logged in this table as succeeded = FALSE for later processing.
+ ****/
+ INSERT INTO pgl_ddl_deploy.subscriber_logs
+ (set_name,
+ provider_pid,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ subscriber_pid,
+ executed_at,
+ ddl_sql,
+ full_ddl_sql,
+ succeeded,
+ error_message)
+ VALUES
+ (p_set_name,
+ p_pid,
+ p_provider_name,
+ p_set_config_id,
+ current_role,
+ pg_backend_pid(),
+ current_timestamp,
+ p_ddl_sql_sent,
+ p_full_ddl,
+ v_succeeded,
+ v_error_message);
+
+END IF;
+
+RETURN v_succeeded;
+
+END;
+$pgl_ddl_deploy_sql$
+LANGUAGE plpgsql VOLATILE;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.queue_ddl_message_type()
+ RETURNS "char"
+ LANGUAGE sql
+ IMMUTABLE
+AS $function$
+SELECT 'Q'::"char";
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.provider_node_name(p_driver pgl_ddl_deploy.driver)
+ RETURNS NAME
+ LANGUAGE plpgsql
+AS $function$
+DECLARE v_node_name NAME;
+BEGIN
+
+IF p_driver = 'pglogical' THEN
+
+ SELECT n.node_name INTO v_node_name
+ FROM pglogical.node n
+ INNER JOIN pglogical.local_node ln
+ USING (node_id);
+ RETURN v_node_name;
+
+ELSEIF p_driver = 'native' THEN
+
+ RETURN NULL::NAME;
+
+ELSE
+
+RAISE EXCEPTION 'Unsupported driver specified';
+
+END IF;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE VIEW pgl_ddl_deploy.event_trigger_schema AS
+WITH vars AS
+(SELECT
+ sc.id,
+ set_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_function_name,
+ 'auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_trigger_name,
+ 'auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_trigger_name,
+ 'auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_trigger_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ create_tags,
+ drop_tags,
+ ddl_only_replication,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ sc.driver,
+
+ /****
+ These constants in DECLARE portion of all functions is identical and can be shared
+ */
+ $BUILD$
+ c_search_path TEXT = (SELECT current_setting('search_path'));
+ c_provider_name TEXT;
+ --TODO: How do I decide which replication set we care about?
+ v_pid INT = pg_backend_pid();
+ v_rec RECORD;
+ v_ddl_sql_raw TEXT;
+ v_ddl_sql_sent TEXT;
+ v_full_ddl TEXT;
+ v_sql_tags TEXT[];
+ v_cmd_rec RECORD;
+ v_subcmd_rec RECORD;
+ v_excluded_subcommands TEXT;
+ v_contains_any_valid_subcommand INT;
+
+ /*****
+ We need to strip the DDL of:
+ 1. Transaction begin and commit, which cannot run inside plpgsql
+ *****/
+ v_ddl_strip_regex TEXT = '(begin\W*transaction\W*|begin\W*work\W*|begin\W*|commit\W*transaction\W*|commit\W*work\W*|commit\W*);';
+ v_txid BIGINT;
+ v_ddl_length INT;
+ v_sql TEXT;
+ v_cmd_count INT;
+ v_match_count INT;
+ v_exclude_always_match_count INT;
+ v_nspname TEXT;
+ v_relname TEXT;
+ v_error TEXT;
+ v_error_detail TEXT;
+ v_context TEXT;
+ v_excluded_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_exception_msg TEXT = 'Deployment exception logged in pgl_ddl_deploy.exceptions';
+
+ --Configurable options in function setup
+ c_set_config_id INT = $BUILD$||sc.id::TEXT||$BUILD$;
+ -- Even though pglogical supports an array of sets, we only pipe DDL through one at a time
+ -- So c_set_name is a text not text[] data type.
+ c_set_name TEXT = '$BUILD$||set_name||$BUILD$';
+ c_driver pgl_ddl_deploy.driver = '$BUILD$||sc.driver||$BUILD$';
+ c_include_schema_regex TEXT = $BUILD$||COALESCE(''''||include_schema_regex||'''','NULL')||$BUILD$;
+ c_lock_safe_deployment BOOLEAN = $BUILD$||lock_safe_deployment||$BUILD$;
+ c_allow_multi_statements BOOLEAN = $BUILD$||allow_multi_statements||$BUILD$;
+ c_include_only_repset_tables BOOLEAN = $BUILD$||include_only_repset_tables||$BUILD$;
+ c_include_everything BOOLEAN = $BUILD$||include_everything||$BUILD$;
+ c_queue_subscriber_failures BOOLEAN = $BUILD$||queue_subscriber_failures||$BUILD$;
+ c_create_tags TEXT[] = '$BUILD$||create_tags::TEXT||$BUILD$';
+ c_blacklisted_tags TEXT[] = '$BUILD$||blacklisted_tags::TEXT||$BUILD$';
+ c_exclude_alter_table_subcommands TEXT[] = $BUILD$||COALESCE(quote_literal(exclude_alter_table_subcommands::TEXT),'NULL')||$BUILD$;
+ c_signal_blocking_subscriber_sessions TEXT = $BUILD$||COALESCE(quote_literal(signal_blocking_subscriber_sessions::TEXT),'NULL')||$BUILD$;
+ c_subscriber_lock_timeout INT = $BUILD$||COALESCE(subscriber_lock_timeout::TEXT,'NULL')||$BUILD$;
+
+ --Constants based on configuration
+ c_exec_prefix TEXT =(CASE
+ WHEN c_lock_safe_deployment
+ THEN 'SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$'
+ ELSE ''
+ END);
+ c_exec_suffix TEXT = (CASE
+ WHEN c_lock_safe_deployment
+ THEN '$PGL_DDL_DEPLOY$);'
+ ELSE ''
+ END);
+ $BUILD$::TEXT AS declare_constants,
+
+ $BUILD$
+ --If there are any matches to our replication config, get the query
+ --This will either be sent, or logged at this point if not deployable
+ IF (c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0 THEN
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+ v_txid = txid_current();
+ END IF;
+ $BUILD$::TEXT AS shared_get_query,
+/****
+ This is the portion of the event trigger function that evaluates if SQL
+ is appropriate to propagate, and does propagate the event. It is shared
+ between the normal and drop event trigger functions.
+ */
+ $BUILD$
+ /****
+ A multi-statement SQL command may fire this event trigger more than once
+ This check ensures the SQL is propagated only once, if at all
+ */
+ IF EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.events
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ OR EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.unhandled
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ THEN
+ RETURN;
+ END IF;
+
+ /****
+ Get the command tags and reject blacklisted tags
+ */
+ v_sql_tags:=(SELECT pgl_ddl_deploy.sql_command_tags(v_ddl_sql_raw));
+ IF (SELECT c_blacklisted_tags && v_sql_tags) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_command_tags',
+ v_txid);
+ RETURN;
+ /****
+ If we are not allowing multi-statements at all, reject
+ */
+ ELSEIF (SELECT ARRAY[TG_TAG]::TEXT[] <> v_sql_tags WHERE NOT c_allow_multi_statements) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_multi_statement',
+ v_txid);
+ RETURN;
+ END IF;
+
+ /****
+ If this is an ALTER TABLE statement and we are excluding any subcommand tags, process now.
+ Note the following.
+
+ Because there can be more than one subcommand, we have a limited ability
+ to filter out subcommands until such a time as we may have a mechanism for rebuilding only
+ the SQL we want. In other words, if we have one subcommand that we DO want (i.e. ADD COLUMN)
+ and one we don't want (i.e. REFERENCES) in the same SQL, and we are "excluding" the latter,
+ we can't do that exclusion safely because we WANT the ADD COLUMN statement. In such a case,
+ we are still going to allow the DDL to go through because it's better to break replication than
+ miss a column addition.
+
+ But if the only subcommand is an excluded one, i.e. ADD CONSTRAINT, then we will indeed ignore
+ the DDL and the function will RETURN without executing replicate_ddl_command.
+ */
+ IF TG_TAG = 'ALTER TABLE' AND c_exclude_alter_table_subcommands IS NOT NULL THEN
+ FOR v_cmd_rec IN
+ SELECT * FROM pg_event_trigger_ddl_commands()
+ LOOP
+ IF pgl_ddl_deploy.get_command_type(v_cmd_rec.command) = 'alter table' THEN
+ WITH subcommands AS (
+ SELECT subcommand,
+ c_exclude_alter_table_subcommands && ARRAY[subcommand] AS subcommand_is_excluded,
+ MAX(CASE WHEN c_exclude_alter_table_subcommands && ARRAY[subcommand] THEN 0 ELSE 1 END) OVER() AS contains_any_valid_subcommand
+ FROM unnest(pgl_ddl_deploy.get_altertable_subcmdinfo(v_cmd_rec.command)) AS subcommand
+ )
+
+ SELECT (SELECT string_agg(subcommand,', ') FROM subcommands WHERE subcommand_is_excluded),
+ (SELECT contains_any_valid_subcommand FROM subcommands LIMIT 1)
+ INTO v_excluded_subcommands,
+ v_contains_any_valid_subcommand;
+ IF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 0 THEN
+ RAISE LOG 'Not processing DDL due to excluded subcommand(s): %: %', v_excluded_subcommands, v_ddl_sql_raw;
+ RETURN;
+ ELSEIF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 1 THEN
+ RAISE WARNING $INNER_BLOCK$Filtering out more than one subcommand in one ALTER TABLE is not supported.
+ Allowing to proceed: Rejected: %, SQL: %$INNER_BLOCK$, v_excluded_subcommands, v_ddl_sql_raw;
+ END IF;
+ END IF;
+ END LOOP;
+ END IF;
+
+ v_ddl_sql_sent = v_ddl_sql_raw;
+
+ --If there are BEGIN/COMMIT tags, attempt to strip and reparse
+ IF (SELECT ARRAY['BEGIN','COMMIT']::TEXT[] && v_sql_tags) THEN
+ v_ddl_sql_sent = regexp_replace(v_ddl_sql_sent, v_ddl_strip_regex, '', 'ig');
+
+ --Sanity reparse
+ PERFORM pgl_ddl_deploy.sql_command_tags(v_ddl_sql_sent);
+ END IF;
+
+ --Get provider name, in order only to run command on a subscriber to this provider
+ c_provider_name:=pgl_ddl_deploy.provider_node_name(c_driver);
+
+ /*
+ Build replication DDL command which will conditionally run only on the subscriber
+ In other words, this MUST be a no-op on the provider
+ **Because the DDL has already run at this point (ddl_command_end)**
+ */
+ v_full_ddl:=$INNER_BLOCK$
+ --Be sure to use provider's search_path for SQL environment consistency
+ SET SEARCH_PATH TO $INNER_BLOCK$||
+ CASE WHEN COALESCE(c_search_path,'') IN('','""') THEN quote_literal('') ELSE c_search_path END||$INNER_BLOCK$;
+
+ $INNER_BLOCK$||c_exec_prefix||v_ddl_sql_sent||c_exec_suffix||$INNER_BLOCK$
+ ;
+ $INNER_BLOCK$;
+ RAISE DEBUG 'v_full_ddl: %', v_full_ddl;
+ RAISE DEBUG 'c_set_config_id: %', c_set_config_id;
+ RAISE DEBUG 'c_set_name: %', c_set_name;
+ RAISE DEBUG 'c_driver: %', c_driver;
+ RAISE DEBUG 'v_ddl_sql_sent: %', v_ddl_sql_sent;
+
+ v_sql:=$INNER_BLOCK$
+ SELECT $BUILD$||CASE
+ WHEN sc.driver = 'native'
+ THEN 'pgl_ddl_deploy'
+ WHEN sc.driver = 'pglogical'
+ THEN 'pglogical'
+ ELSE 'ERROR-EXCEPTION' END||$BUILD$.replicate_ddl_command($REPLICATE_DDL_COMMAND$
+ SELECT pgl_ddl_deploy.subscriber_command
+ (
+ p_provider_name := $INNER_BLOCK$||COALESCE(quote_literal(c_provider_name), 'NULL')||$INNER_BLOCK$,
+ p_set_name := ARRAY[$INNER_BLOCK$||quote_literal(c_set_name)||$INNER_BLOCK$],
+ p_nspname := $INNER_BLOCK$||COALESCE(quote_literal(v_nspname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_relname := $INNER_BLOCK$||COALESCE(quote_literal(v_relname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_ddl_sql_sent := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_ddl_sql_sent||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_full_ddl := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_full_ddl||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_pid := $INNER_BLOCK$||v_pid::TEXT||$INNER_BLOCK$,
+ p_set_config_id := $INNER_BLOCK$||c_set_config_id::TEXT||$INNER_BLOCK$,
+ p_queue_subscriber_failures := $INNER_BLOCK$||c_queue_subscriber_failures||$INNER_BLOCK$,
+ p_signal_blocking_subscriber_sessions := $INNER_BLOCK$||COALESCE(quote_literal(c_signal_blocking_subscriber_sessions),'NULL')||$INNER_BLOCK$,
+ p_lock_timeout := $INNER_BLOCK$||COALESCE(c_subscriber_lock_timeout, 3000)||$INNER_BLOCK$,
+ p_driver := $INNER_BLOCK$||quote_literal(c_driver)||$INNER_BLOCK$
+ );
+ $REPLICATE_DDL_COMMAND$,
+ --Pipe this DDL command through chosen replication set
+ ARRAY['$INNER_BLOCK$||c_set_name||$INNER_BLOCK$']);
+ $INNER_BLOCK$;
+
+ RAISE DEBUG 'v_sql: %', v_sql;
+ EXECUTE v_sql;
+
+ INSERT INTO pgl_ddl_deploy.events
+ (set_config_id,
+ set_name,
+ pid,
+ executed_at,
+ ddl_sql_raw,
+ ddl_sql_sent,
+ txid)
+ VALUES
+ (c_set_config_id,
+ c_set_name,
+ v_pid,
+ current_timestamp,
+ v_ddl_sql_raw,
+ v_ddl_sql_sent,
+ v_txid);
+ $BUILD$::TEXT AS shared_deploy_logic,
+ $BUILD$
+ ELSEIF (v_match_count > 0 AND v_cmd_count <> v_match_count) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'mixed_objects',
+ v_txid);
+ $BUILD$::TEXT AS shared_mixed_obj_logic,
+
+ $BUILD$
+ /**
+ Catch any exceptions and log in a local table
+ As a safeguard, if even the exception handler fails, exit cleanly but add a server log message
+ **/
+ EXCEPTION WHEN OTHERS THEN
+ GET STACKED DIAGNOSTICS
+ v_context = PG_EXCEPTION_CONTEXT,
+ v_error = MESSAGE_TEXT,
+ v_error_detail = PG_EXCEPTION_DETAIL;
+ BEGIN
+ INSERT INTO pgl_ddl_deploy.exceptions (set_config_id, set_name, pid, executed_at, ddl_sql, err_msg, err_state)
+ VALUES (c_set_config_id, c_set_name, v_pid, current_timestamp, v_sql, format('%s %s %s', v_error, v_context, v_error_detail), SQLSTATE);
+ RAISE WARNING '%', c_exception_msg;
+ --No matter what, don't let this function block any DDL
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Unhandled exception % %', SQLERRM, SQLSTATE;
+ END;
+ $BUILD$::TEXT AS shared_exception_handler,
+
+ $BUILD$
+ FROM pg_namespace n
+ INNER JOIN pg_class c ON n.oid = c.relnamespace
+ AND c.relpersistence = 'p'
+ WHERE n.nspname ~* c_include_schema_regex
+ AND n.nspname !~* c_exclude_always
+ AND EXISTS (SELECT 1
+ FROM pg_index i
+ WHERE i.indrelid = c.oid
+ AND i.indisprimary)
+ AND NOT EXISTS
+ (SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.name = c_set_name
+ AND rsr.relid = c.oid
+ AND rsr.driver = c_driver)
+ $BUILD$::TEXT AS shared_repl_set_tables,
+
+ $BUILD$
+ SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name ~* c_include_schema_regex
+ AND schema_name !~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_include_schema_regex
+ AND object_identity !~* c_exclude_always)
+ )
+ )
+ OR
+ --include_only_repset_tables usage:
+ (
+ ($BUILD$||include_only_repset_tables||$BUILD$) AND
+ (EXISTS
+ (
+ SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.relid = c.objid
+ AND c.object_type in('table','table column','table constraint')
+ AND rsr.name = '$BUILD$||sc.set_name||$BUILD$'
+ AND rsr.driver = '$BUILD$||sc.driver||$BUILD$'
+ )
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS match_count,
+ SUM(CASE
+ WHEN
+ --include_everything usage still excludes exclude_always regex:
+ (
+ ($BUILD$||include_everything||$BUILD$) AND
+ (
+ (schema_name ~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_exclude_always)
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS exclude_always_match_count
+ $BUILD$::TEXT AS shared_match_count
+FROM pgl_ddl_deploy.rep_set_wrapper() rs
+INNER JOIN pgl_ddl_deploy.set_configs sc ON sc.set_name = rs.name AND sc.driver = rs.driver
+)
+
+, build AS (
+SELECT
+ id,
+ set_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ auto_replication_create_function_name,
+ auto_replication_drop_function_name,
+ auto_replication_unsupported_function_name,
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name,
+
+CASE WHEN driver = 'pglogical' THEN '--no-op pglogical diver'::TEXT
+WHEN driver = 'native' THEN $BUILD$
+DO $$
+BEGIN
+
+IF NOT EXISTS (SELECT 1
+FROM pg_publication_tables
+WHERE pubname = '$BUILD$||set_name||$BUILD$'
+AND schemaname = 'pgl_ddl_deploy'
+AND tablename = 'queue') THEN
+ ALTER PUBLICATION $BUILD$||quote_ident(set_name)||$BUILD$
+ ADD TABLE pgl_ddl_deploy.queue;
+END IF;
+
+END$$;
+$BUILD$
+END AS add_queue_table_to_replication,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$ || auto_replication_create_function_name || $BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , MAX(c.schema_name)
+ , MAX(cl.relname)
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_nspname, v_relname
+ FROM pg_event_trigger_ddl_commands() c
+ LEFT JOIN LATERAL
+ (SELECT cl.relname
+ FROM pg_class cl
+ WHERE cl.oid = c.objid
+ AND c.classid = (SELECT oid FROM pg_class WHERE relname = 'pg_class')
+ -- There should only be one table modified per event trigger
+ -- At least that's the best we will do now
+ LIMIT 1) cl ON TRUE;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_cmd_count = v_match_count))
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension
+ FROM pg_event_trigger_ddl_commands();
+
+ /**
+ Add table to replication set immediately, if required, and only if the set_config includes CREATE TABLE.
+ We do not filter to tags here, because of possibility of multi-statement SQL.
+ Optional ddl_only_replication will never auto-add tables to replication because the
+ purpose is to only replicate keep the structure synchronized on the subscriber with no data.
+ **/
+ IF c_create_tags && '{"CREATE TABLE"}' AND NOT $BUILD$||include_only_repset_tables||$BUILD$ AND NOT $BUILD$||ddl_only_replication||$BUILD$ THEN
+ PERFORM pgl_ddl_deploy.add_table_to_replication(
+ p_driver:=c_driver
+ ,p_set_name:=c_set_name
+ ,p_relation:=c.oid
+ ,p_synchronize_data:=false
+ )
+ $BUILD$||shared_repl_set_tables||$BUILD$;
+ END IF;
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$::TEXT
+END AS auto_replication_function,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_drop_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name !~* '^(pg_catalog|pg_toast)$'
+ AND schema_name !~* c_include_schema_regex)
+ OR (object_type = 'schema'
+ AND object_identity !~* '^(pg_catalog|pg_toast)$'
+ AND object_identity !~* c_include_schema_regex)
+ )
+ )
+ --include_only_repset_tables cannot be used with DROP because
+ --the objects no longer exist to be checked:
+ THEN 1
+ ELSE 0 END) AS excluded_count
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_excluded_count
+ FROM pg_event_trigger_dropped_objects() c;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_excluded_count = 0))
+
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ TG_TAG,
+ object_type,
+ schema_name,
+ object_identity,
+ NULL
+ FROM pg_event_trigger_dropped_objects();
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_drop_function,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_unsupported_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count
+ FROM pg_event_trigger_ddl_commands() c;
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0)
+ THEN
+
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'unsupported_command',
+ v_txid);
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_unsupported_function,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(create_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$ || auto_replication_create_function_name || $BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_trigger,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ON sql_drop
+WHEN TAG IN('$BUILD$||array_to_string(drop_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$||auto_replication_drop_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_drop_trigger,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(pgl_ddl_deploy.unsupported_tags(),$$','$$)||$BUILD$')
+EXECUTE PROCEDURE $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_unsupported_trigger,
+
+$BUILD$
+DROP TABLE IF EXISTS tmp_objs;
+CREATE TEMP TABLE tmp_objs (obj_type, obj_name) AS (
+VALUES
+('EVENT TRIGGER','$BUILD$||auto_replication_create_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_drop_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_unsupported_trigger_name||$BUILD$'),
+('FUNCTION','$BUILD$||auto_replication_create_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_drop_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_unsupported_function_name||$BUILD$()')
+);
+
+SELECT pgl_ddl_deploy.drop_ext_object(obj_type, obj_name)
+FROM tmp_objs;
+DROP EVENT TRIGGER IF EXISTS $BUILD$||auto_replication_create_trigger_name||', '||auto_replication_drop_trigger_name||', '||auto_replication_unsupported_trigger_name||$BUILD$;
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_create_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_drop_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$
+ AS undeploy_sql
+FROM vars)
+
+SELECT
+ b.id,
+ b.set_name,
+ b.include_schema_regex,
+ b.include_only_repset_tables,
+ b.include_everything,
+ b.signal_blocking_subscriber_sessions,
+ b.subscriber_lock_timeout,
+ b.auto_replication_create_function_name,
+ b.auto_replication_drop_function_name,
+ b.auto_replication_unsupported_function_name,
+ b.auto_replication_create_trigger_name,
+ b.auto_replication_drop_trigger_name,
+ b.auto_replication_unsupported_trigger_name,
+ b.auto_replication_function,
+ b.auto_replication_drop_function,
+ b.auto_replication_unsupported_function,
+ b.auto_replication_trigger,
+ b.auto_replication_drop_trigger,
+ b.auto_replication_unsupported_trigger,
+ b.undeploy_sql,
+ b.undeploy_sql||
+ b.add_queue_table_to_replication||$BUILD$
+ $BUILD$||auto_replication_function||$BUILD$
+ $BUILD$||auto_replication_drop_function||$BUILD$
+ $BUILD$||auto_replication_unsupported_function||$BUILD$
+ $BUILD$||auto_replication_trigger||$BUILD$
+ $BUILD$||auto_replication_drop_trigger||$BUILD$
+ $BUILD$||auto_replication_unsupported_trigger||$BUILD$
+ SELECT pgl_ddl_deploy.add_ext_object(obj_type, obj_name)
+ FROM tmp_objs;
+ $BUILD$ AS deploy_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ DISABLE;
+ $BUILD$ AS disable_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ENABLE;
+ $BUILD$ AS enable_sql,
+ EXISTS (SELECT 1
+ FROM pg_event_trigger
+ WHERE evtname IN(
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name
+ )
+ AND evtenabled IN('O','R','A')
+ ) AS is_deployed
+FROM build b;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.add_role(p_roleoid oid)
+ RETURNS boolean
+ LANGUAGE plpgsql
+AS $function$
+/******
+Assuming roles doing DDL are not superusers, this function grants needed privileges
+to run through the pgl_ddl_deploy DDL deployment.
+This needs to be run on BOTH provider and subscriber.
+******/
+DECLARE
+ v_rec RECORD;
+ v_sql TEXT;
+ v_rsat_args TEXT;
+BEGIN
+
+ FOR v_rec IN
+ SELECT quote_ident(rolname) AS rolname FROM pg_roles WHERE oid = p_roleoid
+ LOOP
+
+ v_sql:='
+ GRANT USAGE ON SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.replicate_ddl_command(text, text[]) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.add_table_to_replication(pgl_ddl_deploy.driver, name, regclass, boolean) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.notify_subscription_refresh(name, boolean) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.sql_command_tags(text) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pgl_ddl_deploy.kill_blockers(pgl_ddl_deploy.signals, name, name) TO '||v_rec.rolname||';
+ GRANT INSERT, UPDATE, SELECT ON ALL TABLES IN SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';
+ GRANT USAGE ON ALL SEQUENCES IN SCHEMA pgl_ddl_deploy TO '||v_rec.rolname||';';
+ EXECUTE v_sql;
+
+ IF EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pglogical') THEN
+ v_rsat_args:=pg_get_function_identity_arguments('pglogical.replication_set_add_table'::REGPROC);
+
+
+ v_sql:='
+ GRANT USAGE ON SCHEMA pglogical TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pglogical.replicate_ddl_command(text, text[]) TO '||v_rec.rolname||';
+ GRANT EXECUTE ON FUNCTION pglogical.replication_set_add_table(' || v_rsat_args || ') TO '||v_rec.rolname||';
+ GRANT SELECT ON ALL TABLES IN SCHEMA pglogical TO '||v_rec.rolname||';';
+ EXECUTE v_sql;
+ END IF;
+
+ RETURN true;
+ END LOOP;
+RETURN false;
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.override() RETURNS BOOLEAN AS $BODY$
+BEGIN
+RETURN FALSE;
+END;
+$BODY$
+LANGUAGE plpgsql IMMUTABLE;
+
+
+-- Now re-deploy event triggers and functions
+SELECT id, pgl_ddl_deploy.deploy(id) AS deployed
+FROM ddl_deploy_to_refresh;
+
+DROP TABLE IF EXISTS ddl_deploy_to_refresh;
+DROP TABLE IF EXISTS tmp_objs;
+
+-- Ensure added roles have write permissions for new tables added
+-- Not so easy to pre-package this with default privileges because
+-- we can't assume everyone uses the same role to deploy this extension
+SELECT pgl_ddl_deploy.add_role(role_oid)
+FROM (
+SELECT DISTINCT r.oid AS role_oid
+FROM information_schema.table_privileges tp
+INNER JOIN pg_roles r ON r.rolname = tp.grantee AND NOT r.rolsuper
+WHERE table_schema = 'pgl_ddl_deploy'
+ AND privilege_type = 'INSERT'
+ AND table_name = 'subscriber_logs'
+) roles_with_existing_privileges;
+
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.add_table_to_replication(pgl_ddl_deploy.driver, name, regclass, boolean) FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.notify_subscription_refresh(name, boolean) FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.kill_blockers(pgl_ddl_deploy.signals, name, name) FROM PUBLIC;
+
+
+/* pgl_ddl_deploy--2.0--2.1.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.execute_queued_ddl()
+ RETURNS trigger
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+
+/***
+Native logical replication does not support row filtering, so as a result,
+we need to do processing downstream to ensure we only process rows we care about.
+
+For example, if we propagate some DDL to system 1 and some other to system 2,
+all rows will still come through this trigger. We filter out rows based on
+matching pubnames with pg_subscription.subpublications
+
+If a row arrives here (the subscriber), it must mean that it was propagated
+***/
+
+-- This handles potential duplicates with multiple subscriptions to same publisher db.
+IF EXISTS (
+SELECT NEW.*
+INTERSECT
+SELECT * FROM pgl_ddl_deploy.queue) THEN
+ RETURN NULL;
+END IF;
+
+IF NEW.message_type = pgl_ddl_deploy.queue_ddl_message_type() AND
+ (pgl_ddl_deploy.override() OR ((SELECT COUNT(1) FROM pg_subscription s
+ WHERE subpublications && NEW.pubnames) > 0)) THEN
+
+ -- See https://www.postgresql.org/message-id/CAMa1XUh7ZVnBzORqjJKYOv4_pDSDUCvELRbkF0VtW7pvDW9rZw@mail.gmail.com
+ IF NEW.message ~* 'pgl_ddl_deploy.notify_subscription_refresh' THEN
+ INSERT INTO pgl_ddl_deploy.subscriber_logs
+ (set_name,
+ provider_pid,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ subscriber_pid,
+ executed_at,
+ ddl_sql,
+ full_ddl_sql,
+ succeeded,
+ error_message)
+ VALUES
+ (NEW.pubnames[1],
+ NULL,
+ NULL,
+ NULL,
+ current_role,
+ pg_backend_pid(),
+ current_timestamp,
+ NEW.message,
+ NEW.message,
+ FALSE,
+ 'Unsupported automated ALTER SUBSCRIPTION ... REFRESH PUBLICATION until bugfix');
+ ELSE
+ EXECUTE 'SET ROLE '||quote_ident(NEW.role)||';';
+ EXECUTE NEW.message::TEXT;
+ END IF;
+
+ RETURN NEW;
+ELSE
+ RETURN NULL;
+END IF;
+
+END;
+$function$
+;
+
+
+/* pgl_ddl_deploy--2.1--2.2.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+/*
+ * We need to re-deploy the trigger function definitions
+ * which will have changed with this extension update. So
+ * here we undeploy them, and save which ones we need to
+ * recreate later.
+*/
+DO $$
+BEGIN
+
+IF EXISTS (SELECT 1 FROM pg_views WHERE schemaname = 'pgl_ddl_deploy' AND viewname = 'event_trigger_schema') THEN
+
+DROP TABLE IF EXISTS ddl_deploy_to_refresh;
+CREATE TEMP TABLE ddl_deploy_to_refresh AS
+SELECT id, pgl_ddl_deploy.undeploy(id) AS undeployed
+FROM pgl_ddl_deploy.event_trigger_schema
+WHERE is_deployed;
+
+-- it needs to be modified, so now we drop it to recreate later
+DROP VIEW pgl_ddl_deploy.event_trigger_schema;
+
+ELSE
+
+DROP TABLE IF EXISTS ddl_deploy_to_refresh;
+CREATE TEMP TABLE ddl_deploy_to_refresh AS
+SELECT NULL::INT AS id;
+
+END IF;
+END$$;
+
+DROP FUNCTION IF EXISTS pgl_ddl_deploy.get_altertable_subcmdinfo(pg_ddl_command);
+DROP FUNCTION IF EXISTS pgl_ddl_deploy.get_altertable_subcmdtypes(pg_ddl_command);
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.execute_queued_ddl()
+ RETURNS trigger
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+
+/***
+Native logical replication does not support row filtering, so as a result,
+we need to do processing downstream to ensure we only process rows we care about.
+
+For example, if we propagate some DDL to system 1 and some other to system 2,
+all rows will still come through this trigger. We filter out rows based on
+matching pubnames with pg_subscription.subpublications
+
+If a row arrives here (the subscriber), it must mean that it was propagated
+***/
+
+-- This handles potential duplicates with multiple subscriptions to same publisher db.
+IF EXISTS (
+SELECT NEW.*
+INTERSECT
+SELECT * FROM pgl_ddl_deploy.queue) THEN
+ RETURN NULL;
+END IF;
+
+IF NEW.message_type = pgl_ddl_deploy.queue_ddl_message_type() AND
+ (pgl_ddl_deploy.override() OR ((SELECT COUNT(1) FROM pg_subscription s
+ WHERE subpublications && NEW.pubnames) > 0)) THEN
+
+ -- See https://www.postgresql.org/message-id/CAMa1XUh7ZVnBzORqjJKYOv4_pDSDUCvELRbkF0VtW7pvDW9rZw@mail.gmail.com
+ IF NEW.message ~* 'pgl_ddl_deploy.notify_subscription_refresh' THEN
+ INSERT INTO pgl_ddl_deploy.subscriber_logs
+ (set_name,
+ provider_pid,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ subscriber_pid,
+ executed_at,
+ ddl_sql,
+ full_ddl_sql,
+ succeeded,
+ error_message)
+ VALUES
+ (NEW.pubnames[1],
+ NULL,
+ NULL,
+ NULL,
+ current_role,
+ pg_backend_pid(),
+ current_timestamp,
+ NEW.message,
+ NEW.message,
+ FALSE,
+ 'Unsupported automated ALTER SUBSCRIPTION ... REFRESH PUBLICATION until bugfix');
+ ELSE
+ EXECUTE 'SET ROLE '||quote_ident(NEW.role)||';';
+ EXECUTE NEW.message::TEXT;
+ END IF;
+
+ RETURN NEW;
+ELSE
+ RETURN NULL;
+END IF;
+
+END;
+$function$
+;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.get_altertable_subcmdinfo(pg_ddl_command)
+ RETURNS text[] IMMUTABLE STRICT
+ AS '$libdir/ddl_deparse', 'get_altertable_subcmdinfo' LANGUAGE C;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.subscriber_command
+(
+ p_provider_name NAME,
+ p_set_name TEXT[],
+ p_nspname NAME,
+ p_relname NAME,
+ p_ddl_sql_sent TEXT,
+ p_full_ddl TEXT,
+ p_pid INT,
+ p_set_config_id INT,
+ p_queue_subscriber_failures BOOLEAN,
+ p_signal_blocking_subscriber_sessions pgl_ddl_deploy.signals,
+ p_lock_timeout INT,
+ p_driver pgl_ddl_deploy.driver,
+-- This parameter currently only exists to make testing this function easier
+ p_run_anywhere BOOLEAN = FALSE
+)
+RETURNS BOOLEAN
+AS $function$
+/****
+This function is what will actually be executed on the subscriber when attempting to apply DDL
+changed. It is sent to subscriber(s) via pglogical.replicate_ddl_command. You can see how it
+is called based on the the view pgl_ddl_deploy.event_trigger_schema, which is used to create the
+specific event trigger functions that will call this function in different ways depending on
+configuration in pgl_ddl_deploy.set_configs.
+
+This function is also used to make testing easier. The regression suite calls
+this function to verify basic functionality.
+****/
+DECLARE
+ v_succeeded BOOLEAN;
+ v_error_message TEXT;
+ v_attempt_number INT = 0;
+ v_signal pgl_ddl_deploy.signals;
+BEGIN
+
+IF pgl_ddl_deploy.is_subscriber(p_driver, p_set_name, p_provider_name) OR p_run_anywhere THEN
+
+ v_error_message = NULL;
+ /****
+ If we have configured to kill blocking subscribers, here we set parameters for that:
+ 1. Whether to cancel or terminate
+ 2. What lock_timeout to tolerate
+ ****/
+ IF p_signal_blocking_subscriber_sessions IS NOT NULL THEN
+ v_signal = CASE WHEN p_signal_blocking_subscriber_sessions = 'cancel_then_terminate' THEN 'cancel' ELSE p_signal_blocking_subscriber_sessions END;
+ -- We cannot RESET LOCAL lock_timeout but that should not be necessary because it will end with the transaction
+ EXECUTE format('SET LOCAL lock_timeout TO %s', p_lock_timeout);
+ END IF;
+
+ /****
+ Loop until one of the following takes place:
+ 1. Successful DDL execution on first attempt
+ 2. An unexpected ERROR occurs, which will either RAISE or finish with WARNING based on queue_subscriber_failures configuration
+ 3. Blocking sessions are killed until we finally get a successful DDL execution
+ ****/
+ WHILE TRUE LOOP
+ BEGIN
+
+ --Execute DDL
+ RAISE LOG 'pgl_ddl_deploy attempting execution: %', p_full_ddl;
+
+ --Execute DDL - the reason we use execute here is partly to handle no trailing semicolon
+ EXECUTE p_full_ddl;
+
+ v_succeeded = TRUE;
+ EXIT;
+
+ EXCEPTION
+ WHEN lock_not_available THEN
+ IF p_signal_blocking_subscriber_sessions IS NOT NULL THEN
+ -- Change to terminate if we are using cancel_then_terminate and have not been successful after the first iteration
+ IF v_attempt_number > 0 AND p_signal_blocking_subscriber_sessions = 'cancel_then_terminate' AND v_signal = 'cancel' THEN
+ v_signal = 'terminate';
+ END IF;
+ INSERT INTO pgl_ddl_deploy.killed_blockers
+ (signal,
+ successful,
+ pid,
+ executed_at,
+ usename,
+ client_addr,
+ xact_start,
+ state_change,
+ state,
+ query,
+ reported)
+ SELECT
+ signal,
+ successful,
+ pid,
+ executed_at,
+ usename,
+ client_addr,
+ xact_start,
+ state_change,
+ state,
+ query,
+ reported
+ FROM pgl_ddl_deploy.kill_blockers(
+ v_signal,
+ p_nspname,
+ p_relname
+ );
+
+ -- Continue and retry again but allow a brief pause
+ v_attempt_number = v_attempt_number + 1;
+ PERFORM pg_sleep(3);
+ ELSE
+ -- If p_signal_blocking_subscriber_sessions is not configured but we hit a lock_timeout,
+ -- then the replication user or cluster is configured with a global lock_timeout. Raise in this case.
+ RAISE;
+ END IF;
+ WHEN OTHERS THEN
+ IF p_queue_subscriber_failures THEN
+ RAISE WARNING 'Subscriber DDL failed with errors (see pgl_ddl_deploy.subscriber_logs): %', SQLERRM;
+ v_succeeded = FALSE;
+ v_error_message = SQLERRM;
+ EXIT;
+ ELSE
+ RAISE;
+ END IF;
+ END;
+ END LOOP;
+
+ /****
+ Since this function is only executed on the subscriber, this INSERT adds a log
+ to subscriber_logs on the subscriber after execution.
+
+ Note that if we configured queue_subscriber_failures to TRUE in pgl_ddl_deploy.set_configs, then we are
+ allowing failed DDL to be caught and logged in this table as succeeded = FALSE for later processing.
+ ****/
+ INSERT INTO pgl_ddl_deploy.subscriber_logs
+ (set_name,
+ provider_pid,
+ provider_node_name,
+ provider_set_config_id,
+ executed_as_role,
+ subscriber_pid,
+ executed_at,
+ ddl_sql,
+ full_ddl_sql,
+ succeeded,
+ error_message)
+ VALUES
+ (p_set_name,
+ p_pid,
+ p_provider_name,
+ p_set_config_id,
+ current_role,
+ pg_backend_pid(),
+ current_timestamp,
+ p_ddl_sql_sent,
+ p_full_ddl,
+ v_succeeded,
+ v_error_message);
+
+END IF;
+
+RETURN v_succeeded;
+
+END;
+$function$
+LANGUAGE plpgsql VOLATILE;
+
+
+CREATE OR REPLACE VIEW pgl_ddl_deploy.event_trigger_schema AS
+WITH vars AS
+(SELECT
+ sc.id,
+ set_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_function_name,
+ 'auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_trigger_name,
+ 'auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_trigger_name,
+ 'auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_trigger_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ create_tags,
+ drop_tags,
+ ddl_only_replication,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ sc.driver,
+
+ /****
+ These constants in DECLARE portion of all functions is identical and can be shared
+ */
+ $BUILD$
+ c_search_path TEXT = (SELECT current_setting('search_path'));
+ c_provider_name TEXT;
+ --TODO: How do I decide which replication set we care about?
+ v_pid INT = pg_backend_pid();
+ v_rec RECORD;
+ v_ddl_sql_raw TEXT;
+ v_ddl_sql_sent TEXT;
+ v_full_ddl TEXT;
+ v_sql_tags TEXT[];
+ v_cmd_rec RECORD;
+ v_subcmd_rec RECORD;
+ v_excluded_subcommands TEXT;
+ v_contains_any_valid_subcommand INT;
+
+ /*****
+ We need to strip the DDL of:
+ 1. Transaction begin and commit, which cannot run inside plpgsql
+ *****/
+ v_ddl_strip_regex TEXT = '(begin\W*transaction\W*|begin\W*work\W*|begin\W*|commit\W*transaction\W*|commit\W*work\W*|commit\W*);';
+ v_txid BIGINT;
+ v_ddl_length INT;
+ v_sql TEXT;
+ v_cmd_count INT;
+ v_match_count INT;
+ v_exclude_always_match_count INT;
+ v_nspname TEXT;
+ v_relname TEXT;
+ v_error TEXT;
+ v_error_detail TEXT;
+ v_context TEXT;
+ v_excluded_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_exception_msg TEXT = 'Deployment exception logged in pgl_ddl_deploy.exceptions';
+
+ --Configurable options in function setup
+ c_set_config_id INT = $BUILD$||sc.id::TEXT||$BUILD$;
+ -- Even though pglogical supports an array of sets, we only pipe DDL through one at a time
+ -- So c_set_name is a text not text[] data type.
+ c_set_name TEXT = '$BUILD$||set_name||$BUILD$';
+ c_driver pgl_ddl_deploy.driver = '$BUILD$||sc.driver||$BUILD$';
+ c_include_schema_regex TEXT = $BUILD$||COALESCE(''''||include_schema_regex||'''','NULL')||$BUILD$;
+ c_lock_safe_deployment BOOLEAN = $BUILD$||lock_safe_deployment||$BUILD$;
+ c_allow_multi_statements BOOLEAN = $BUILD$||allow_multi_statements||$BUILD$;
+ c_include_only_repset_tables BOOLEAN = $BUILD$||include_only_repset_tables||$BUILD$;
+ c_include_everything BOOLEAN = $BUILD$||include_everything||$BUILD$;
+ c_queue_subscriber_failures BOOLEAN = $BUILD$||queue_subscriber_failures||$BUILD$;
+ c_create_tags TEXT[] = '$BUILD$||create_tags::TEXT||$BUILD$';
+ c_blacklisted_tags TEXT[] = '$BUILD$||blacklisted_tags::TEXT||$BUILD$';
+ c_exclude_alter_table_subcommands TEXT[] = $BUILD$||COALESCE(quote_literal(exclude_alter_table_subcommands::TEXT),'NULL')||$BUILD$;
+ c_signal_blocking_subscriber_sessions TEXT = $BUILD$||COALESCE(quote_literal(signal_blocking_subscriber_sessions::TEXT),'NULL')||$BUILD$;
+ c_subscriber_lock_timeout INT = $BUILD$||COALESCE(subscriber_lock_timeout::TEXT,'NULL')||$BUILD$;
+
+ --Constants based on configuration
+ c_exec_prefix TEXT =(CASE
+ WHEN c_lock_safe_deployment
+ THEN 'SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$'
+ ELSE ''
+ END);
+ c_exec_suffix TEXT = (CASE
+ WHEN c_lock_safe_deployment
+ THEN '$PGL_DDL_DEPLOY$);'
+ ELSE ''
+ END);
+ $BUILD$::TEXT AS declare_constants,
+
+ $BUILD$
+ --If there are any matches to our replication config, get the query
+ --This will either be sent, or logged at this point if not deployable
+ IF (c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0 THEN
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+ v_txid = txid_current();
+ END IF;
+ $BUILD$::TEXT AS shared_get_query,
+/****
+ This is the portion of the event trigger function that evaluates if SQL
+ is appropriate to propagate, and does propagate the event. It is shared
+ between the normal and drop event trigger functions.
+ */
+ $BUILD$
+ /****
+ A multi-statement SQL command may fire this event trigger more than once
+ This check ensures the SQL is propagated only once, if at all
+ */
+ IF EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.events
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ OR EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.unhandled
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ THEN
+ RETURN;
+ END IF;
+
+ /****
+ Get the command tags and reject blacklisted tags
+ */
+ v_sql_tags:=(SELECT pgl_ddl_deploy.sql_command_tags(v_ddl_sql_raw));
+ IF (SELECT c_blacklisted_tags && v_sql_tags) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_command_tags',
+ v_txid);
+ RETURN;
+ /****
+ If we are not allowing multi-statements at all, reject
+ */
+ ELSEIF (SELECT ARRAY[TG_TAG]::TEXT[] <> v_sql_tags WHERE NOT c_allow_multi_statements) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_multi_statement',
+ v_txid);
+ RETURN;
+ END IF;
+
+ /****
+ If this is an ALTER TABLE statement and we are excluding any subcommand tags, process now.
+ Note the following.
+
+ Because there can be more than one subcommand, we have a limited ability
+ to filter out subcommands until such a time as we may have a mechanism for rebuilding only
+ the SQL we want. In other words, if we have one subcommand that we DO want (i.e. ADD COLUMN)
+ and one we don't want (i.e. REFERENCES) in the same SQL, and we are "excluding" the latter,
+ we can't do that exclusion safely because we WANT the ADD COLUMN statement. In such a case,
+ we are still going to allow the DDL to go through because it's better to break replication than
+ miss a column addition.
+
+ But if the only subcommand is an excluded one, i.e. ADD CONSTRAINT, then we will indeed ignore
+ the DDL and the function will RETURN without executing replicate_ddl_command.
+ */
+ IF TG_TAG = 'ALTER TABLE' AND c_exclude_alter_table_subcommands IS NOT NULL THEN
+ FOR v_cmd_rec IN
+ SELECT * FROM pg_event_trigger_ddl_commands()
+ LOOP
+ IF pgl_ddl_deploy.get_command_type(v_cmd_rec.command) = 'alter table' THEN
+ WITH subcommands AS (
+ SELECT subcommand,
+ c_exclude_alter_table_subcommands && ARRAY[subcommand] AS subcommand_is_excluded,
+ MAX(CASE WHEN c_exclude_alter_table_subcommands && ARRAY[subcommand] THEN 0 ELSE 1 END) OVER() AS contains_any_valid_subcommand
+ FROM unnest(pgl_ddl_deploy.get_altertable_subcmdinfo(v_cmd_rec.command)) AS subcommand
+ )
+
+ SELECT (SELECT string_agg(subcommand,', ') FROM subcommands WHERE subcommand_is_excluded),
+ (SELECT contains_any_valid_subcommand FROM subcommands LIMIT 1)
+ INTO v_excluded_subcommands,
+ v_contains_any_valid_subcommand;
+ IF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 0 THEN
+ RAISE LOG 'Not processing DDL due to excluded subcommand(s): %: %', v_excluded_subcommands, v_ddl_sql_raw;
+ RETURN;
+ ELSEIF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 1 THEN
+ RAISE WARNING $INNER_BLOCK$Filtering out more than one subcommand in one ALTER TABLE is not supported.
+ Allowing to proceed: Rejected: %, SQL: %$INNER_BLOCK$, v_excluded_subcommands, v_ddl_sql_raw;
+ END IF;
+ END IF;
+ END LOOP;
+ END IF;
+
+ v_ddl_sql_sent = v_ddl_sql_raw;
+
+ --If there are BEGIN/COMMIT tags, attempt to strip and reparse
+ IF (SELECT ARRAY['BEGIN','COMMIT']::TEXT[] && v_sql_tags) THEN
+ v_ddl_sql_sent = regexp_replace(v_ddl_sql_sent, v_ddl_strip_regex, '', 'ig');
+
+ --Sanity reparse
+ PERFORM pgl_ddl_deploy.sql_command_tags(v_ddl_sql_sent);
+ END IF;
+
+ --Get provider name, in order only to run command on a subscriber to this provider
+ c_provider_name:=pgl_ddl_deploy.provider_node_name(c_driver);
+
+ /*
+ Build replication DDL command which will conditionally run only on the subscriber
+ In other words, this MUST be a no-op on the provider
+ **Because the DDL has already run at this point (ddl_command_end)**
+ */
+ v_full_ddl:=$INNER_BLOCK$
+ --Be sure to use provider's search_path for SQL environment consistency
+ SET SEARCH_PATH TO $INNER_BLOCK$||
+ CASE WHEN COALESCE(c_search_path,'') IN('','""') THEN quote_literal('') ELSE c_search_path END||$INNER_BLOCK$;
+
+ $INNER_BLOCK$||c_exec_prefix||v_ddl_sql_sent||c_exec_suffix||$INNER_BLOCK$
+ ;
+ $INNER_BLOCK$;
+ RAISE DEBUG 'v_full_ddl: %', v_full_ddl;
+ RAISE DEBUG 'c_set_config_id: %', c_set_config_id;
+ RAISE DEBUG 'c_set_name: %', c_set_name;
+ RAISE DEBUG 'c_driver: %', c_driver;
+ RAISE DEBUG 'v_ddl_sql_sent: %', v_ddl_sql_sent;
+
+ v_sql:=$INNER_BLOCK$
+ SELECT $BUILD$||CASE
+ WHEN sc.driver = 'native'
+ THEN 'pgl_ddl_deploy'
+ WHEN sc.driver = 'pglogical'
+ THEN 'pglogical'
+ ELSE 'ERROR-EXCEPTION' END||$BUILD$.replicate_ddl_command($REPLICATE_DDL_COMMAND$
+ SELECT pgl_ddl_deploy.subscriber_command
+ (
+ p_provider_name := $INNER_BLOCK$||COALESCE(quote_literal(c_provider_name), 'NULL')||$INNER_BLOCK$,
+ p_set_name := ARRAY[$INNER_BLOCK$||quote_literal(c_set_name)||$INNER_BLOCK$],
+ p_nspname := $INNER_BLOCK$||COALESCE(quote_literal(v_nspname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_relname := $INNER_BLOCK$||COALESCE(quote_literal(v_relname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_ddl_sql_sent := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_ddl_sql_sent||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_full_ddl := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_full_ddl||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_pid := $INNER_BLOCK$||v_pid::TEXT||$INNER_BLOCK$,
+ p_set_config_id := $INNER_BLOCK$||c_set_config_id::TEXT||$INNER_BLOCK$,
+ p_queue_subscriber_failures := $INNER_BLOCK$||c_queue_subscriber_failures||$INNER_BLOCK$,
+ p_signal_blocking_subscriber_sessions := $INNER_BLOCK$||COALESCE(quote_literal(c_signal_blocking_subscriber_sessions),'NULL')||$INNER_BLOCK$,
+ p_lock_timeout := $INNER_BLOCK$||COALESCE(c_subscriber_lock_timeout, 3000)||$INNER_BLOCK$,
+ p_driver := $INNER_BLOCK$||quote_literal(c_driver)||$INNER_BLOCK$
+ );
+ $REPLICATE_DDL_COMMAND$,
+ --Pipe this DDL command through chosen replication set
+ ARRAY['$INNER_BLOCK$||c_set_name||$INNER_BLOCK$']);
+ $INNER_BLOCK$;
+
+ RAISE DEBUG 'v_sql: %', v_sql;
+ EXECUTE v_sql;
+
+ INSERT INTO pgl_ddl_deploy.events
+ (set_config_id,
+ set_name,
+ pid,
+ executed_at,
+ ddl_sql_raw,
+ ddl_sql_sent,
+ txid)
+ VALUES
+ (c_set_config_id,
+ c_set_name,
+ v_pid,
+ current_timestamp,
+ v_ddl_sql_raw,
+ v_ddl_sql_sent,
+ v_txid);
+ $BUILD$::TEXT AS shared_deploy_logic,
+ $BUILD$
+ ELSEIF (v_match_count > 0 AND v_cmd_count <> v_match_count) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'mixed_objects',
+ v_txid);
+ $BUILD$::TEXT AS shared_mixed_obj_logic,
+
+ $BUILD$
+ /**
+ Catch any exceptions and log in a local table
+ As a safeguard, if even the exception handler fails, exit cleanly but add a server log message
+ **/
+ EXCEPTION WHEN OTHERS THEN
+ GET STACKED DIAGNOSTICS
+ v_context = PG_EXCEPTION_CONTEXT,
+ v_error = MESSAGE_TEXT,
+ v_error_detail = PG_EXCEPTION_DETAIL;
+ BEGIN
+ INSERT INTO pgl_ddl_deploy.exceptions (set_config_id, set_name, pid, executed_at, ddl_sql, err_msg, err_state)
+ VALUES (c_set_config_id, c_set_name, v_pid, current_timestamp, v_sql, format('%s %s %s', v_error, v_context, v_error_detail), SQLSTATE);
+ RAISE WARNING '%', c_exception_msg;
+ --No matter what, don't let this function block any DDL
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Unhandled exception % %', SQLERRM, SQLSTATE;
+ END;
+ $BUILD$::TEXT AS shared_exception_handler,
+
+ $BUILD$
+ FROM pg_namespace n
+ INNER JOIN pg_class c ON n.oid = c.relnamespace
+ AND c.relpersistence = 'p'
+ WHERE n.nspname ~* c_include_schema_regex
+ AND n.nspname !~* c_exclude_always
+ AND EXISTS (SELECT 1
+ FROM pg_index i
+ WHERE i.indrelid = c.oid
+ AND i.indisprimary)
+ AND NOT EXISTS
+ (SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.name = c_set_name
+ AND rsr.relid = c.oid
+ AND rsr.driver = c_driver)
+ $BUILD$::TEXT AS shared_repl_set_tables,
+
+ $BUILD$
+ SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name ~* c_include_schema_regex
+ AND schema_name !~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_include_schema_regex
+ AND object_identity !~* c_exclude_always)
+ )
+ )
+ OR
+ --include_only_repset_tables usage:
+ (
+ ($BUILD$||include_only_repset_tables||$BUILD$) AND
+ (EXISTS
+ (
+ SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.relid = c.objid
+ AND c.object_type in('table','table column','table constraint')
+ AND rsr.name = '$BUILD$||sc.set_name||$BUILD$'
+ AND rsr.driver = '$BUILD$||sc.driver||$BUILD$'
+ )
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS match_count,
+ SUM(CASE
+ WHEN
+ --include_everything usage still excludes exclude_always regex:
+ (
+ ($BUILD$||include_everything||$BUILD$) AND
+ (
+ (schema_name ~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_exclude_always)
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS exclude_always_match_count
+ $BUILD$::TEXT AS shared_match_count
+FROM pgl_ddl_deploy.rep_set_wrapper() rs
+INNER JOIN pgl_ddl_deploy.set_configs sc ON sc.set_name = rs.name AND sc.driver = rs.driver
+)
+
+, build AS (
+SELECT
+ id,
+ set_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ auto_replication_create_function_name,
+ auto_replication_drop_function_name,
+ auto_replication_unsupported_function_name,
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name,
+
+CASE WHEN driver = 'pglogical' THEN '--no-op pglogical diver'::TEXT
+WHEN driver = 'native' THEN $BUILD$
+DO $$
+BEGIN
+
+IF NOT EXISTS (SELECT 1
+FROM pg_publication_tables
+WHERE pubname = '$BUILD$||set_name||$BUILD$'
+AND schemaname = 'pgl_ddl_deploy'
+AND tablename = 'queue') THEN
+ ALTER PUBLICATION $BUILD$||quote_ident(set_name)||$BUILD$
+ ADD TABLE pgl_ddl_deploy.queue;
+END IF;
+
+END$$;
+$BUILD$
+END AS add_queue_table_to_replication,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$ || auto_replication_create_function_name || $BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , MAX(c.schema_name)
+ , MAX(cl.relname)
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_nspname, v_relname
+ FROM pg_event_trigger_ddl_commands() c
+ LEFT JOIN LATERAL
+ (SELECT cl.relname
+ FROM pg_class cl
+ WHERE cl.oid = c.objid
+ AND c.classid = (SELECT oid FROM pg_class WHERE relname = 'pg_class')
+ -- There should only be one table modified per event trigger
+ -- At least that's the best we will do now
+ LIMIT 1) cl ON TRUE;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_cmd_count = v_match_count))
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension
+ FROM pg_event_trigger_ddl_commands();
+
+ /**
+ Add table to replication set immediately, if required, and only if the set_config includes CREATE TABLE.
+ We do not filter to tags here, because of possibility of multi-statement SQL.
+ Optional ddl_only_replication will never auto-add tables to replication because the
+ purpose is to only replicate keep the structure synchronized on the subscriber with no data.
+ **/
+ IF c_create_tags && '{"CREATE TABLE"}' AND NOT $BUILD$||include_only_repset_tables||$BUILD$ AND NOT $BUILD$||ddl_only_replication||$BUILD$ THEN
+ PERFORM pgl_ddl_deploy.add_table_to_replication(
+ p_driver:=c_driver
+ ,p_set_name:=c_set_name
+ ,p_relation:=c.oid
+ ,p_synchronize_data:=false
+ )
+ $BUILD$||shared_repl_set_tables||$BUILD$;
+ END IF;
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$::TEXT
+END AS auto_replication_function,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_drop_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name !~* '^(pg_catalog|pg_toast)$'
+ AND schema_name !~* c_include_schema_regex)
+ OR (object_type = 'schema'
+ AND object_identity !~* '^(pg_catalog|pg_toast)$'
+ AND object_identity !~* c_include_schema_regex)
+ )
+ )
+ --include_only_repset_tables cannot be used with DROP because
+ --the objects no longer exist to be checked:
+ THEN 1
+ ELSE 0 END) AS excluded_count
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_excluded_count
+ FROM pg_event_trigger_dropped_objects() c;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_excluded_count = 0))
+
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ TG_TAG,
+ object_type,
+ schema_name,
+ object_identity,
+ NULL
+ FROM pg_event_trigger_dropped_objects();
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_drop_function,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_unsupported_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count
+ FROM pg_event_trigger_ddl_commands() c;
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0)
+ THEN
+
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'unsupported_command',
+ v_txid);
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_unsupported_function,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(create_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$ || auto_replication_create_function_name || $BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_trigger,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ON sql_drop
+WHEN TAG IN('$BUILD$||array_to_string(drop_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$||auto_replication_drop_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_drop_trigger,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(pgl_ddl_deploy.unsupported_tags(),$$','$$)||$BUILD$')
+EXECUTE PROCEDURE $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_unsupported_trigger,
+
+$BUILD$
+DROP TABLE IF EXISTS tmp_objs;
+CREATE TEMP TABLE tmp_objs (obj_type, obj_name) AS (
+VALUES
+('EVENT TRIGGER','$BUILD$||auto_replication_create_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_drop_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_unsupported_trigger_name||$BUILD$'),
+('FUNCTION','$BUILD$||auto_replication_create_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_drop_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_unsupported_function_name||$BUILD$()')
+);
+
+SELECT pgl_ddl_deploy.drop_ext_object(obj_type, obj_name)
+FROM tmp_objs;
+DROP EVENT TRIGGER IF EXISTS $BUILD$||auto_replication_create_trigger_name||', '||auto_replication_drop_trigger_name||', '||auto_replication_unsupported_trigger_name||$BUILD$;
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_create_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_drop_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$
+ AS undeploy_sql
+FROM vars)
+
+SELECT
+ b.id,
+ b.set_name,
+ b.include_schema_regex,
+ b.include_only_repset_tables,
+ b.include_everything,
+ b.signal_blocking_subscriber_sessions,
+ b.subscriber_lock_timeout,
+ b.auto_replication_create_function_name,
+ b.auto_replication_drop_function_name,
+ b.auto_replication_unsupported_function_name,
+ b.auto_replication_create_trigger_name,
+ b.auto_replication_drop_trigger_name,
+ b.auto_replication_unsupported_trigger_name,
+ b.auto_replication_function,
+ b.auto_replication_drop_function,
+ b.auto_replication_unsupported_function,
+ b.auto_replication_trigger,
+ b.auto_replication_drop_trigger,
+ b.auto_replication_unsupported_trigger,
+ b.undeploy_sql,
+ b.undeploy_sql||
+ b.add_queue_table_to_replication||$BUILD$
+ $BUILD$||auto_replication_function||$BUILD$
+ $BUILD$||auto_replication_drop_function||$BUILD$
+ $BUILD$||auto_replication_unsupported_function||$BUILD$
+ $BUILD$||auto_replication_trigger||$BUILD$
+ $BUILD$||auto_replication_drop_trigger||$BUILD$
+ $BUILD$||auto_replication_unsupported_trigger||$BUILD$
+ SELECT pgl_ddl_deploy.add_ext_object(obj_type, obj_name)
+ FROM tmp_objs;
+ $BUILD$ AS deploy_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ DISABLE;
+ $BUILD$ AS disable_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ENABLE;
+ $BUILD$ AS enable_sql,
+ EXISTS (SELECT 1
+ FROM pg_event_trigger
+ WHERE evtname IN(
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name
+ )
+ AND evtenabled IN('O','R','A')
+ ) AS is_deployed
+FROM build b;
+
+
+-- Now re-deploy event triggers and functions
+SELECT id, pgl_ddl_deploy.deploy(id) AS deployed
+FROM ddl_deploy_to_refresh;
+
+DROP TABLE IF EXISTS ddl_deploy_to_refresh;
+DROP TABLE IF EXISTS tmp_objs;
+
+-- Ensure added roles have write permissions for new tables added
+-- Not so easy to pre-package this with default privileges because
+-- we can't assume everyone uses the same role to deploy this extension
+SELECT pgl_ddl_deploy.add_role(role_oid)
+FROM (
+SELECT DISTINCT r.oid AS role_oid
+FROM information_schema.table_privileges tp
+INNER JOIN pg_roles r ON r.rolname = tp.grantee AND NOT r.rolsuper
+WHERE table_schema = 'pgl_ddl_deploy'
+ AND privilege_type = 'INSERT'
+ AND table_name = 'subscriber_logs'
+) roles_with_existing_privileges;
+
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.add_table_to_replication(pgl_ddl_deploy.driver, name, regclass, boolean) FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.notify_subscription_refresh(name, boolean) FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pgl_ddl_deploy.kill_blockers(pgl_ddl_deploy.signals, name, name) FROM PUBLIC;
+
+
+/* pgl_ddl_deploy--2.2--2.3.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+CREATE OR REPLACE VIEW pgl_ddl_deploy.event_trigger_schema AS
+WITH vars AS
+(SELECT
+ sc.id,
+ set_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_function_name,
+ 'auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_trigger_name,
+ 'auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_trigger_name,
+ 'auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_trigger_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ create_tags,
+ drop_tags,
+ ddl_only_replication,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ sc.driver,
+
+ /****
+ These constants in DECLARE portion of all functions is identical and can be shared
+ */
+ $BUILD$
+ c_search_path TEXT = (SELECT current_setting('search_path'));
+ c_provider_name TEXT;
+ --TODO: How do I decide which replication set we care about?
+ v_pid INT = pg_backend_pid();
+ v_rec RECORD;
+ v_ddl_sql_raw TEXT;
+ v_ddl_sql_sent TEXT;
+ v_full_ddl TEXT;
+ v_sql_tags TEXT[];
+ v_cmd_rec RECORD;
+ v_subcmd_rec RECORD;
+ v_excluded_subcommands TEXT;
+ v_contains_any_valid_subcommand INT;
+
+ /*****
+ We need to strip the DDL of:
+ 1. Transaction begin and commit, which cannot run inside plpgsql
+ *****/
+ v_ddl_strip_regex TEXT = '(begin\W*transaction\W*|begin\W*work\W*|begin\W*|commit\W*transaction\W*|commit\W*work\W*|commit\W*);';
+ v_txid BIGINT;
+ v_ddl_length INT;
+ v_sql TEXT;
+ v_cmd_count INT;
+ v_match_count INT;
+ v_exclude_always_match_count INT;
+ v_nspname TEXT;
+ v_relname TEXT;
+ v_error TEXT;
+ v_error_detail TEXT;
+ v_context TEXT;
+ v_excluded_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_exception_msg TEXT = 'Deployment exception logged in pgl_ddl_deploy.exceptions';
+
+ --Configurable options in function setup
+ c_set_config_id INT = $BUILD$||sc.id::TEXT||$BUILD$;
+ -- Even though pglogical supports an array of sets, we only pipe DDL through one at a time
+ -- So c_set_name is a text not text[] data type.
+ c_set_name TEXT = '$BUILD$||set_name||$BUILD$';
+ c_driver pgl_ddl_deploy.driver = '$BUILD$||sc.driver||$BUILD$';
+ c_include_schema_regex TEXT = $BUILD$||COALESCE(''''||include_schema_regex||'''','NULL')||$BUILD$;
+ c_lock_safe_deployment BOOLEAN = $BUILD$||lock_safe_deployment||$BUILD$;
+ c_allow_multi_statements BOOLEAN = $BUILD$||allow_multi_statements||$BUILD$;
+ c_include_only_repset_tables BOOLEAN = $BUILD$||include_only_repset_tables||$BUILD$;
+ c_include_everything BOOLEAN = $BUILD$||include_everything||$BUILD$;
+ c_queue_subscriber_failures BOOLEAN = $BUILD$||queue_subscriber_failures||$BUILD$;
+ c_create_tags TEXT[] = '$BUILD$||create_tags::TEXT||$BUILD$';
+ c_blacklisted_tags TEXT[] = '$BUILD$||blacklisted_tags::TEXT||$BUILD$';
+ c_exclude_alter_table_subcommands TEXT[] = $BUILD$||COALESCE(quote_literal(exclude_alter_table_subcommands::TEXT),'NULL')||$BUILD$;
+ c_signal_blocking_subscriber_sessions TEXT = $BUILD$||COALESCE(quote_literal(signal_blocking_subscriber_sessions::TEXT),'NULL')||$BUILD$;
+ c_subscriber_lock_timeout INT = $BUILD$||COALESCE(subscriber_lock_timeout::TEXT,'NULL')||$BUILD$;
+
+ --Constants based on configuration
+ c_exec_prefix TEXT =(CASE
+ WHEN c_lock_safe_deployment
+ THEN 'SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$'
+ ELSE ''
+ END);
+ c_exec_suffix TEXT = (CASE
+ WHEN c_lock_safe_deployment
+ THEN '$PGL_DDL_DEPLOY$);'
+ ELSE ''
+ END);
+ $BUILD$::TEXT AS declare_constants,
+
+ $BUILD$
+ --If there are any matches to our replication config, get the query
+ --This will either be sent, or logged at this point if not deployable
+ IF (c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0 THEN
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+ v_txid = txid_current();
+ END IF;
+ $BUILD$::TEXT AS shared_get_query,
+/****
+ This is the portion of the event trigger function that evaluates if SQL
+ is appropriate to propagate, and does propagate the event. It is shared
+ between the normal and drop event trigger functions.
+ */
+ $BUILD$
+ /****
+ A multi-statement SQL command may fire this event trigger more than once
+ This check ensures the SQL is propagated only once, if at all
+ */
+ IF EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.events
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ OR EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.unhandled
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ THEN
+ RETURN;
+ END IF;
+
+ /****
+ Get the command tags and reject blacklisted tags
+ */
+ v_sql_tags:=(SELECT pgl_ddl_deploy.sql_command_tags(v_ddl_sql_raw));
+ IF (SELECT c_blacklisted_tags && v_sql_tags) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_command_tags',
+ v_txid);
+ RETURN;
+ /****
+ If we are not allowing multi-statements at all, reject
+ */
+ ELSEIF (SELECT ARRAY[TG_TAG]::TEXT[] <> v_sql_tags WHERE NOT c_allow_multi_statements) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_multi_statement',
+ v_txid);
+ RETURN;
+ END IF;
+
+ /****
+ If this is an ALTER TABLE statement and we are excluding any subcommand tags, process now.
+ Note the following.
+
+ Because there can be more than one subcommand, we have a limited ability
+ to filter out subcommands until such a time as we may have a mechanism for rebuilding only
+ the SQL we want. In other words, if we have one subcommand that we DO want (i.e. ADD COLUMN)
+ and one we don't want (i.e. REFERENCES) in the same SQL, and we are "excluding" the latter,
+ we can't do that exclusion safely because we WANT the ADD COLUMN statement. In such a case,
+ we are still going to allow the DDL to go through because it's better to break replication than
+ miss a column addition.
+
+ But if the only subcommand is an excluded one, i.e. ADD CONSTRAINT, then we will indeed ignore
+ the DDL and the function will RETURN without executing replicate_ddl_command.
+ */
+ IF TG_TAG = 'ALTER TABLE' AND c_exclude_alter_table_subcommands IS NOT NULL THEN
+ FOR v_cmd_rec IN
+ SELECT * FROM pg_event_trigger_ddl_commands()
+ LOOP
+ IF pgl_ddl_deploy.get_command_type(v_cmd_rec.command) = 'alter table' THEN
+ WITH subcommands AS (
+ SELECT subcommand,
+ c_exclude_alter_table_subcommands && ARRAY[subcommand] AS subcommand_is_excluded,
+ MAX(CASE WHEN c_exclude_alter_table_subcommands && ARRAY[subcommand] THEN 0 ELSE 1 END) OVER() AS contains_any_valid_subcommand
+ FROM unnest(pgl_ddl_deploy.get_altertable_subcmdinfo(v_cmd_rec.command)) AS subcommand
+ )
+
+ SELECT (SELECT string_agg(subcommand,', ') FROM subcommands WHERE subcommand_is_excluded),
+ (SELECT contains_any_valid_subcommand FROM subcommands LIMIT 1)
+ INTO v_excluded_subcommands,
+ v_contains_any_valid_subcommand;
+ IF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 0 THEN
+ RAISE LOG 'Not processing DDL due to excluded subcommand(s): %: %', v_excluded_subcommands, v_ddl_sql_raw;
+ RETURN;
+ ELSEIF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 1 THEN
+ RAISE WARNING $INNER_BLOCK$Filtering out more than one subcommand in one ALTER TABLE is not supported.
+ Allowing to proceed: Rejected: %, SQL: %$INNER_BLOCK$, v_excluded_subcommands, v_ddl_sql_raw;
+ END IF;
+ END IF;
+ END LOOP;
+ END IF;
+
+ v_ddl_sql_sent = v_ddl_sql_raw;
+
+ --If there are BEGIN/COMMIT tags, attempt to strip and reparse
+ IF (SELECT ARRAY['BEGIN','COMMIT']::TEXT[] && v_sql_tags) THEN
+ v_ddl_sql_sent = regexp_replace(v_ddl_sql_sent, v_ddl_strip_regex, '', 'ig');
+
+ --Sanity reparse
+ PERFORM pgl_ddl_deploy.sql_command_tags(v_ddl_sql_sent);
+ END IF;
+
+ --Get provider name, in order only to run command on a subscriber to this provider
+ c_provider_name:=pgl_ddl_deploy.provider_node_name(c_driver);
+
+ /*
+ Build replication DDL command which will conditionally run only on the subscriber
+ In other words, this MUST be a no-op on the provider
+ **Because the DDL has already run at this point (ddl_command_end)**
+ */
+ v_full_ddl:=$INNER_BLOCK$
+ --Be sure to use provider's search_path for SQL environment consistency
+ SET SEARCH_PATH TO $INNER_BLOCK$||
+ CASE WHEN COALESCE(c_search_path,'') IN('','""') THEN quote_literal('') ELSE c_search_path END||$INNER_BLOCK$;
+
+ $INNER_BLOCK$||c_exec_prefix||v_ddl_sql_sent||c_exec_suffix||$INNER_BLOCK$
+ ;
+ $INNER_BLOCK$;
+ RAISE DEBUG 'v_full_ddl: %', v_full_ddl;
+ RAISE DEBUG 'c_set_config_id: %', c_set_config_id;
+ RAISE DEBUG 'c_set_name: %', c_set_name;
+ RAISE DEBUG 'c_driver: %', c_driver;
+ RAISE DEBUG 'v_ddl_sql_sent: %', v_ddl_sql_sent;
+
+ v_sql:=$INNER_BLOCK$
+ SELECT $BUILD$||CASE
+ WHEN sc.driver = 'native'
+ THEN 'pgl_ddl_deploy'
+ WHEN sc.driver = 'pglogical'
+ THEN 'pglogical'
+ ELSE 'ERROR-EXCEPTION' END||$BUILD$.replicate_ddl_command($REPLICATE_DDL_COMMAND$
+ SELECT pgl_ddl_deploy.subscriber_command
+ (
+ p_provider_name := $INNER_BLOCK$||COALESCE(quote_literal(c_provider_name), 'NULL')||$INNER_BLOCK$,
+ p_set_name := ARRAY[$INNER_BLOCK$||quote_literal(c_set_name)||$INNER_BLOCK$],
+ p_nspname := $INNER_BLOCK$||COALESCE(quote_literal(v_nspname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_relname := $INNER_BLOCK$||COALESCE(quote_literal(v_relname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_ddl_sql_sent := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_ddl_sql_sent||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_full_ddl := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_full_ddl||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_pid := $INNER_BLOCK$||v_pid::TEXT||$INNER_BLOCK$,
+ p_set_config_id := $INNER_BLOCK$||c_set_config_id::TEXT||$INNER_BLOCK$,
+ p_queue_subscriber_failures := $INNER_BLOCK$||c_queue_subscriber_failures||$INNER_BLOCK$,
+ p_signal_blocking_subscriber_sessions := $INNER_BLOCK$||COALESCE(quote_literal(c_signal_blocking_subscriber_sessions),'NULL')||$INNER_BLOCK$,
+ p_lock_timeout := $INNER_BLOCK$||COALESCE(c_subscriber_lock_timeout, 3000)||$INNER_BLOCK$,
+ p_driver := $INNER_BLOCK$||quote_literal(c_driver)||$INNER_BLOCK$
+ );
+ $REPLICATE_DDL_COMMAND$,
+ --Pipe this DDL command through chosen replication set
+ ARRAY['$INNER_BLOCK$||c_set_name||$INNER_BLOCK$']);
+ $INNER_BLOCK$;
+
+ RAISE DEBUG 'v_sql: %', v_sql;
+ EXECUTE v_sql;
+
+ INSERT INTO pgl_ddl_deploy.events
+ (set_config_id,
+ set_name,
+ pid,
+ executed_at,
+ ddl_sql_raw,
+ ddl_sql_sent,
+ txid)
+ VALUES
+ (c_set_config_id,
+ c_set_name,
+ v_pid,
+ current_timestamp,
+ v_ddl_sql_raw,
+ v_ddl_sql_sent,
+ v_txid);
+ $BUILD$::TEXT AS shared_deploy_logic,
+ $BUILD$
+ ELSEIF (v_match_count > 0 AND v_cmd_count <> v_match_count) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'mixed_objects',
+ v_txid);
+ $BUILD$::TEXT AS shared_mixed_obj_logic,
+ $BUILD$
+ -- Filter out purely PG-internal triggers (alas, "pg_event_trigger_dropped_objects" does not expose "tgisinternal", so we must filter by name)
+ (SELECT * FROM pg_event_trigger_dropped_objects() WHERE address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_a_%' AND address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_c_%')
+ $BUILD$::TEXT AS dropped_objects_query,
+
+ $BUILD$
+ /**
+ Catch any exceptions and log in a local table
+ As a safeguard, if even the exception handler fails, exit cleanly but add a server log message
+ **/
+ EXCEPTION WHEN OTHERS THEN
+ GET STACKED DIAGNOSTICS
+ v_context = PG_EXCEPTION_CONTEXT,
+ v_error = MESSAGE_TEXT,
+ v_error_detail = PG_EXCEPTION_DETAIL;
+ BEGIN
+ INSERT INTO pgl_ddl_deploy.exceptions (set_config_id, set_name, pid, executed_at, ddl_sql, err_msg, err_state)
+ VALUES (c_set_config_id, c_set_name, v_pid, current_timestamp, v_sql, format('%s %s %s', v_error, v_context, v_error_detail), SQLSTATE);
+ RAISE WARNING '% (%: % - %)', c_exception_msg, v_error, v_context, v_error_detail;
+ --No matter what, don't let this function block any DDL
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Unhandled exception % %', SQLERRM, SQLSTATE;
+ END;
+ $BUILD$::TEXT AS shared_exception_handler,
+
+ $BUILD$
+ FROM pg_namespace n
+ INNER JOIN pg_class c ON n.oid = c.relnamespace
+ AND c.relpersistence = 'p'
+ WHERE n.nspname ~* c_include_schema_regex
+ AND n.nspname !~* c_exclude_always
+ AND EXISTS (SELECT 1
+ FROM pg_index i
+ WHERE i.indrelid = c.oid
+ AND i.indisprimary)
+ AND NOT EXISTS
+ (SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.name = c_set_name
+ AND rsr.relid = c.oid
+ AND rsr.driver = c_driver)
+ $BUILD$::TEXT AS shared_repl_set_tables,
+
+ $BUILD$
+ SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name ~* c_include_schema_regex
+ AND schema_name !~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_include_schema_regex
+ AND object_identity !~* c_exclude_always)
+ )
+ )
+ OR
+ --include_only_repset_tables usage:
+ (
+ ($BUILD$||include_only_repset_tables||$BUILD$) AND
+ (EXISTS
+ (
+ SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.relid = c.objid
+ AND c.object_type in('table','table column','table constraint')
+ AND rsr.name = '$BUILD$||sc.set_name||$BUILD$'
+ AND rsr.driver = '$BUILD$||sc.driver||$BUILD$'
+ )
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS match_count,
+ SUM(CASE
+ WHEN
+ --include_everything usage still excludes exclude_always regex:
+ (
+ ($BUILD$||include_everything||$BUILD$) AND
+ (
+ (schema_name ~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_exclude_always)
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS exclude_always_match_count
+ $BUILD$::TEXT AS shared_match_count
+FROM pgl_ddl_deploy.rep_set_wrapper() rs
+INNER JOIN pgl_ddl_deploy.set_configs sc ON sc.set_name = rs.name AND sc.driver = rs.driver
+)
+
+, build AS (
+SELECT
+ id,
+ set_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ auto_replication_create_function_name,
+ auto_replication_drop_function_name,
+ auto_replication_unsupported_function_name,
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name,
+
+CASE WHEN driver = 'pglogical' THEN '--no-op pglogical diver'::TEXT
+WHEN driver = 'native' THEN $BUILD$
+DO $$
+BEGIN
+
+IF NOT EXISTS (SELECT 1
+FROM pg_publication_tables
+WHERE pubname = '$BUILD$||set_name||$BUILD$'
+AND schemaname = 'pgl_ddl_deploy'
+AND tablename = 'queue') THEN
+ ALTER PUBLICATION $BUILD$||quote_ident(set_name)||$BUILD$
+ ADD TABLE pgl_ddl_deploy.queue;
+END IF;
+
+END$$;
+$BUILD$
+END AS add_queue_table_to_replication,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$ || auto_replication_create_function_name || $BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , MAX(c.schema_name)
+ , MAX(cl.relname)
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_nspname, v_relname
+ FROM pg_event_trigger_ddl_commands() c
+ LEFT JOIN LATERAL
+ (SELECT cl.relname
+ FROM pg_class cl
+ WHERE cl.oid = c.objid
+ AND c.classid = (SELECT oid FROM pg_class WHERE relname = 'pg_class')
+ -- There should only be one table modified per event trigger
+ -- At least that's the best we will do now
+ LIMIT 1) cl ON TRUE;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_cmd_count = v_match_count))
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension
+ FROM pg_event_trigger_ddl_commands();
+
+ /**
+ Add table to replication set immediately, if required, and only if the set_config includes CREATE TABLE.
+ We do not filter to tags here, because of possibility of multi-statement SQL.
+ Optional ddl_only_replication will never auto-add tables to replication because the
+ purpose is to only replicate keep the structure synchronized on the subscriber with no data.
+ **/
+ IF c_create_tags && '{"CREATE TABLE"}' AND NOT $BUILD$||include_only_repset_tables||$BUILD$ AND NOT $BUILD$||ddl_only_replication||$BUILD$ THEN
+ PERFORM pgl_ddl_deploy.add_table_to_replication(
+ p_driver:=c_driver
+ ,p_set_name:=c_set_name
+ ,p_relation:=c.oid
+ ,p_synchronize_data:=false
+ )
+ $BUILD$||shared_repl_set_tables||$BUILD$;
+ END IF;
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$::TEXT
+END AS auto_replication_function,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_drop_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name !~* '^(pg_catalog|pg_toast)$'
+ AND schema_name !~* c_include_schema_regex)
+ OR (object_type = 'schema'
+ AND object_identity !~* '^(pg_catalog|pg_toast)$'
+ AND object_identity !~* c_include_schema_regex)
+ )
+ )
+ --include_only_repset_tables cannot be used with DROP because
+ --the objects no longer exist to be checked:
+ THEN 1
+ ELSE 0 END) AS excluded_count
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_excluded_count
+ FROM $BUILD$||dropped_objects_query||$BUILD$ as c;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_excluded_count = 0))
+
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ TG_TAG,
+ object_type,
+ schema_name,
+ object_identity,
+ NULL
+ FROM $BUILD$||dropped_objects_query||$BUILD$ as c;
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_drop_function,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_unsupported_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count
+ FROM pg_event_trigger_ddl_commands() c;
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0)
+ THEN
+
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'unsupported_command',
+ v_txid);
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_unsupported_function,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(create_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$ || auto_replication_create_function_name || $BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_trigger,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ON sql_drop
+WHEN TAG IN('$BUILD$||array_to_string(drop_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$||auto_replication_drop_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_drop_trigger,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(pgl_ddl_deploy.unsupported_tags(),$$','$$)||$BUILD$')
+EXECUTE PROCEDURE $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_unsupported_trigger,
+
+$BUILD$
+DROP TABLE IF EXISTS tmp_objs;
+CREATE TEMP TABLE tmp_objs (obj_type, obj_name) AS (
+VALUES
+('EVENT TRIGGER','$BUILD$||auto_replication_create_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_drop_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_unsupported_trigger_name||$BUILD$'),
+('FUNCTION','$BUILD$||auto_replication_create_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_drop_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_unsupported_function_name||$BUILD$()')
+);
+
+SELECT pgl_ddl_deploy.drop_ext_object(obj_type, obj_name)
+FROM tmp_objs;
+DROP EVENT TRIGGER IF EXISTS $BUILD$||auto_replication_create_trigger_name||', '||auto_replication_drop_trigger_name||', '||auto_replication_unsupported_trigger_name||$BUILD$;
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_create_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_drop_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$
+ AS undeploy_sql
+FROM vars)
+
+SELECT
+ b.id,
+ b.set_name,
+ b.include_schema_regex,
+ b.include_only_repset_tables,
+ b.include_everything,
+ b.signal_blocking_subscriber_sessions,
+ b.subscriber_lock_timeout,
+ b.auto_replication_create_function_name,
+ b.auto_replication_drop_function_name,
+ b.auto_replication_unsupported_function_name,
+ b.auto_replication_create_trigger_name,
+ b.auto_replication_drop_trigger_name,
+ b.auto_replication_unsupported_trigger_name,
+ b.auto_replication_function,
+ b.auto_replication_drop_function,
+ b.auto_replication_unsupported_function,
+ b.auto_replication_trigger,
+ b.auto_replication_drop_trigger,
+ b.auto_replication_unsupported_trigger,
+ b.undeploy_sql,
+ b.undeploy_sql||
+ b.add_queue_table_to_replication||$BUILD$
+ $BUILD$||auto_replication_function||$BUILD$
+ $BUILD$||auto_replication_drop_function||$BUILD$
+ $BUILD$||auto_replication_unsupported_function||$BUILD$
+ $BUILD$||auto_replication_trigger||$BUILD$
+ $BUILD$||auto_replication_drop_trigger||$BUILD$
+ $BUILD$||auto_replication_unsupported_trigger||$BUILD$
+ SELECT pgl_ddl_deploy.add_ext_object(obj_type, obj_name)
+ FROM tmp_objs;
+ $BUILD$ AS deploy_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ DISABLE;
+ $BUILD$ AS disable_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ENABLE;
+ $BUILD$ AS enable_sql,
+ EXISTS (SELECT 1
+ FROM pg_event_trigger
+ WHERE evtname IN(
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name
+ )
+ AND evtenabled IN('O','R','A')
+ ) AS is_deployed
+FROM build b;
+
+
+/* pgl_ddl_deploy--2.3--2.4.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION pgl_ddl_deploy" to load this file. \quit
+
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN include_indexes BOOLEAN NOT NULL DEFAULT FALSE;
+
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.common_exclude_alter_table_subcommands()
+RETURNS TEXT[] AS
+$BODY$
+SELECT ARRAY[
+ 'ADD CONSTRAINT',
+ '(re) ADD CONSTRAINT',
+ 'ALTER CONSTRAINT',
+ 'VALIDATE CONSTRAINT',
+ 'ADD (processed) CONSTRAINT',
+ 'ADD CONSTRAINT (using index)',
+ 'DROP CONSTRAINT',
+ 'SET LOGGED',
+ 'SET UNLOGGED',
+ 'SET TABLESPACE',
+ 'SET RELOPTIONS',
+ 'RESET RELOPTIONS',
+ 'REPLACE RELOPTIONS',
+ 'ENABLE TRIGGER',
+ 'ENABLE TRIGGER (always)',
+ 'ENABLE TRIGGER (replica)',
+ 'DISABLE TRIGGER',
+ 'ENABLE TRIGGER (all)',
+ 'DISABLE TRIGGER (all)',
+ 'ENABLE TRIGGER (user)',
+ 'DISABLE TRIGGER (user)',
+ 'ENABLE RULE',
+ 'ENABLE RULE (always)',
+ 'ENABLE RULE (replica)',
+ 'DISABLE RULE',
+ 'SET OPTIONS']::TEXT[];
+$BODY$
+LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.rewrite_transaction_safe(p_sql text)
+ RETURNS text
+ LANGUAGE c
+ STRICT
+AS '$libdir/pgl_ddl_deploy', $function$rewrite_transaction_safe$function$
+;
+
+CREATE OR REPLACE FUNCTION pgl_ddl_deploy.set_tag_defaults()
+ RETURNS trigger
+ LANGUAGE plpgsql
+AS $function$
+BEGIN
+IF NEW.create_tags IS NULL THEN
+ NEW.create_tags = CASE WHEN NEW.include_only_repset_tables THEN pgl_ddl_deploy.standard_repset_only_tags() ELSE pgl_ddl_deploy.standard_create_tags() END;
+ IF NEW.include_indexes AND NOT NEW.include_only_repset_tables THEN
+ NEW.create_tags = NEW.create_tags || '{"CREATE INDEX","ALTER INDEX"}'::TEXT[];
+ END IF;
+END IF;
+IF NEW.drop_tags IS NULL THEN
+ NEW.drop_tags = CASE WHEN NEW.include_only_repset_tables THEN NULL ELSE pgl_ddl_deploy.standard_drop_tags() END;
+ IF NEW.include_indexes AND NOT NEW.include_only_repset_tables THEN
+ NEW.drop_tags = NEW.drop_tags || '{"DROP INDEX"}'::TEXT[];
+ END IF;
+END IF;
+RETURN NEW;
+END;
+$function$
+;
+
+CREATE OR REPLACE VIEW pgl_ddl_deploy.event_trigger_schema AS
+WITH vars AS
+(SELECT
+ sc.id,
+ set_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_function_name,
+ 'pgl_ddl_deploy.auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_function_name,
+ 'auto_rep_ddl_create_'||sc.id::TEXT||'_'||set_name AS auto_replication_create_trigger_name,
+ 'auto_rep_ddl_drop_'||sc.id::TEXT||'_'||set_name AS auto_replication_drop_trigger_name,
+ 'auto_rep_ddl_unsupp_'||sc.id::TEXT||'_'||set_name AS auto_replication_unsupported_trigger_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ create_tags,
+ drop_tags,
+ ddl_only_replication,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ sc.driver,
+
+ /****
+ These constants in DECLARE portion of all functions is identical and can be shared
+ */
+ $BUILD$
+ c_search_path TEXT = (SELECT current_setting('search_path'));
+ c_provider_name TEXT;
+ --TODO: How do I decide which replication set we care about?
+ v_pid INT = pg_backend_pid();
+ v_rec RECORD;
+ v_ddl_sql_raw TEXT;
+ v_ddl_sql_sent TEXT;
+ v_full_ddl TEXT;
+ v_sql_tags TEXT[];
+ v_cmd_rec RECORD;
+ v_subcmd_rec RECORD;
+ v_excluded_subcommands TEXT;
+ v_contains_any_valid_subcommand INT;
+
+ /*****
+ We need to strip the DDL of:
+ 1. Transaction begin and commit, which cannot run inside plpgsql
+ *****/
+ v_txid BIGINT;
+ v_ddl_length INT;
+ v_sql TEXT;
+ v_cmd_count INT;
+ v_match_count INT;
+ v_exclude_always_match_count INT;
+ v_nspname TEXT;
+ v_relname TEXT;
+ v_error TEXT;
+ v_error_detail TEXT;
+ v_context TEXT;
+ v_excluded_count INT;
+ c_exclude_always TEXT = pgl_ddl_deploy.exclude_regex();
+ c_exception_msg TEXT = 'Deployment exception logged in pgl_ddl_deploy.exceptions';
+
+ --Configurable options in function setup
+ c_set_config_id INT = $BUILD$||sc.id::TEXT||$BUILD$;
+ -- Even though pglogical supports an array of sets, we only pipe DDL through one at a time
+ -- So c_set_name is a text not text[] data type.
+ c_set_name TEXT = '$BUILD$||set_name||$BUILD$';
+ c_driver pgl_ddl_deploy.driver = '$BUILD$||sc.driver||$BUILD$';
+ c_include_schema_regex TEXT = $BUILD$||COALESCE(''''||include_schema_regex||'''','NULL')||$BUILD$;
+ c_lock_safe_deployment BOOLEAN = $BUILD$||lock_safe_deployment||$BUILD$;
+ c_allow_multi_statements BOOLEAN = $BUILD$||allow_multi_statements||$BUILD$;
+ c_include_only_repset_tables BOOLEAN = $BUILD$||include_only_repset_tables||$BUILD$;
+ c_include_everything BOOLEAN = $BUILD$||include_everything||$BUILD$;
+ c_queue_subscriber_failures BOOLEAN = $BUILD$||queue_subscriber_failures||$BUILD$;
+ c_create_tags TEXT[] = '$BUILD$||create_tags::TEXT||$BUILD$';
+ c_blacklisted_tags TEXT[] = '$BUILD$||blacklisted_tags::TEXT||$BUILD$';
+ c_exclude_alter_table_subcommands TEXT[] = $BUILD$||COALESCE(quote_literal(exclude_alter_table_subcommands::TEXT),'NULL')||$BUILD$;
+ c_signal_blocking_subscriber_sessions TEXT = $BUILD$||COALESCE(quote_literal(signal_blocking_subscriber_sessions::TEXT),'NULL')||$BUILD$;
+ c_subscriber_lock_timeout INT = $BUILD$||COALESCE(subscriber_lock_timeout::TEXT,'NULL')||$BUILD$;
+
+ --Constants based on configuration
+ c_exec_prefix TEXT =(CASE
+ WHEN c_lock_safe_deployment
+ THEN 'SELECT pgl_ddl_deploy.lock_safe_executor($PGL_DDL_DEPLOY$'
+ ELSE ''
+ END);
+ c_exec_suffix TEXT = (CASE
+ WHEN c_lock_safe_deployment
+ THEN '$PGL_DDL_DEPLOY$);'
+ ELSE ''
+ END);
+ $BUILD$::TEXT AS declare_constants,
+
+ $BUILD$
+ --If there are any matches to our replication config, get the query
+ --This will either be sent, or logged at this point if not deployable
+ IF (c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0 THEN
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+ v_txid = txid_current();
+ END IF;
+ $BUILD$::TEXT AS shared_get_query,
+/****
+ This is the portion of the event trigger function that evaluates if SQL
+ is appropriate to propagate, and does propagate the event. It is shared
+ between the normal and drop event trigger functions.
+ */
+ $BUILD$
+ /****
+ A multi-statement SQL command may fire this event trigger more than once
+ This check ensures the SQL is propagated only once, if at all
+ */
+ IF EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.events
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ OR EXISTS
+ (SELECT 1 FROM pgl_ddl_deploy.unhandled
+ WHERE set_name = c_set_name
+ AND txid = v_txid
+ AND ddl_sql_raw = v_ddl_sql_raw
+ AND pid = v_pid)
+ THEN
+ RETURN;
+ END IF;
+
+ /****
+ Get the command tags and reject blacklisted tags
+ */
+ v_sql_tags:=(SELECT pgl_ddl_deploy.sql_command_tags(v_ddl_sql_raw));
+ IF (SELECT c_blacklisted_tags && v_sql_tags) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_command_tags',
+ v_txid);
+ RETURN;
+ /****
+ If we are not allowing multi-statements at all, reject
+ */
+ ELSEIF (SELECT ARRAY[TG_TAG]::TEXT[] <> v_sql_tags WHERE NOT c_allow_multi_statements) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'rejected_multi_statement',
+ v_txid);
+ RETURN;
+ END IF;
+
+ /****
+ If this is an ALTER TABLE statement and we are excluding any subcommand tags, process now.
+ Note the following.
+
+ Because there can be more than one subcommand, we have a limited ability
+ to filter out subcommands until such a time as we may have a mechanism for rebuilding only
+ the SQL we want. In other words, if we have one subcommand that we DO want (i.e. ADD COLUMN)
+ and one we don't want (i.e. REFERENCES) in the same SQL, and we are "excluding" the latter,
+ we can't do that exclusion safely because we WANT the ADD COLUMN statement. In such a case,
+ we are still going to allow the DDL to go through because it's better to break replication than
+ miss a column addition.
+
+ But if the only subcommand is an excluded one, i.e. ADD CONSTRAINT, then we will indeed ignore
+ the DDL and the function will RETURN without executing replicate_ddl_command.
+ */
+ IF TG_TAG = 'ALTER TABLE' AND c_exclude_alter_table_subcommands IS NOT NULL THEN
+ FOR v_cmd_rec IN
+ SELECT * FROM pg_event_trigger_ddl_commands()
+ LOOP
+ IF pgl_ddl_deploy.get_command_type(v_cmd_rec.command) = 'alter table' THEN
+ WITH subcommands AS (
+ SELECT subcommand,
+ c_exclude_alter_table_subcommands && ARRAY[subcommand] AS subcommand_is_excluded,
+ MAX(CASE WHEN c_exclude_alter_table_subcommands && ARRAY[subcommand] THEN 0 ELSE 1 END) OVER() AS contains_any_valid_subcommand
+ FROM unnest(pgl_ddl_deploy.get_altertable_subcmdinfo(v_cmd_rec.command)) AS subcommand
+ )
+
+ SELECT (SELECT string_agg(subcommand,', ') FROM subcommands WHERE subcommand_is_excluded),
+ (SELECT contains_any_valid_subcommand FROM subcommands LIMIT 1)
+ INTO v_excluded_subcommands,
+ v_contains_any_valid_subcommand;
+ IF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 0 THEN
+ RAISE LOG 'Not processing DDL due to excluded subcommand(s): %: %', v_excluded_subcommands, v_ddl_sql_raw;
+ RETURN;
+ ELSEIF v_excluded_subcommands IS NOT NULL AND v_contains_any_valid_subcommand = 1 THEN
+ RAISE WARNING $INNER_BLOCK$Filtering out more than one subcommand in one ALTER TABLE is not supported.
+ Allowing to proceed: Rejected: %, SQL: %$INNER_BLOCK$, v_excluded_subcommands, v_ddl_sql_raw;
+ END IF;
+ END IF;
+ END LOOP;
+ END IF;
+
+ SELECT pgl_ddl_deploy.rewrite_transaction_safe(v_ddl_sql_raw) INTO v_ddl_sql_sent;
+
+ --Get provider name, in order only to run command on a subscriber to this provider
+ c_provider_name:=pgl_ddl_deploy.provider_node_name(c_driver);
+
+ /*
+ Build replication DDL command which will conditionally run only on the subscriber
+ In other words, this MUST be a no-op on the provider
+ **Because the DDL has already run at this point (ddl_command_end)**
+ */
+ v_full_ddl:=$INNER_BLOCK$
+ --Be sure to use provider's search_path for SQL environment consistency
+ SET SEARCH_PATH TO $INNER_BLOCK$||
+ CASE WHEN COALESCE(c_search_path,'') IN('','""') THEN quote_literal('') ELSE c_search_path END||$INNER_BLOCK$;
+
+ $INNER_BLOCK$||c_exec_prefix||v_ddl_sql_sent||c_exec_suffix||$INNER_BLOCK$
+ ;
+ $INNER_BLOCK$;
+ RAISE DEBUG 'v_full_ddl: %', v_full_ddl;
+ RAISE DEBUG 'c_set_config_id: %', c_set_config_id;
+ RAISE DEBUG 'c_set_name: %', c_set_name;
+ RAISE DEBUG 'c_driver: %', c_driver;
+ RAISE DEBUG 'v_ddl_sql_sent: %', v_ddl_sql_sent;
+
+ v_sql:=$INNER_BLOCK$
+ SELECT $BUILD$||CASE
+ WHEN sc.driver = 'native'
+ THEN 'pgl_ddl_deploy'
+ WHEN sc.driver = 'pglogical'
+ THEN 'pglogical'
+ ELSE 'ERROR-EXCEPTION' END||$BUILD$.replicate_ddl_command($REPLICATE_DDL_COMMAND$
+ SELECT pgl_ddl_deploy.subscriber_command
+ (
+ p_provider_name := $INNER_BLOCK$||COALESCE(quote_literal(c_provider_name), 'NULL')||$INNER_BLOCK$,
+ p_set_name := ARRAY[$INNER_BLOCK$||quote_literal(c_set_name)||$INNER_BLOCK$],
+ p_nspname := $INNER_BLOCK$||COALESCE(quote_literal(v_nspname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_relname := $INNER_BLOCK$||COALESCE(quote_literal(v_relname), 'NULL')::TEXT||$INNER_BLOCK$,
+ p_ddl_sql_sent := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_ddl_sql_sent||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_full_ddl := $pgl_ddl_deploy_sql$$INNER_BLOCK$||v_full_ddl||$INNER_BLOCK$$pgl_ddl_deploy_sql$,
+ p_pid := $INNER_BLOCK$||v_pid::TEXT||$INNER_BLOCK$,
+ p_set_config_id := $INNER_BLOCK$||c_set_config_id::TEXT||$INNER_BLOCK$,
+ p_queue_subscriber_failures := $INNER_BLOCK$||c_queue_subscriber_failures||$INNER_BLOCK$,
+ p_signal_blocking_subscriber_sessions := $INNER_BLOCK$||COALESCE(quote_literal(c_signal_blocking_subscriber_sessions),'NULL')||$INNER_BLOCK$,
+ p_lock_timeout := $INNER_BLOCK$||COALESCE(c_subscriber_lock_timeout, 3000)||$INNER_BLOCK$,
+ p_driver := $INNER_BLOCK$||quote_literal(c_driver)||$INNER_BLOCK$
+ );
+ $REPLICATE_DDL_COMMAND$,
+ --Pipe this DDL command through chosen replication set
+ ARRAY['$INNER_BLOCK$||c_set_name||$INNER_BLOCK$']);
+ $INNER_BLOCK$;
+
+ RAISE DEBUG 'v_sql: %', v_sql;
+ EXECUTE v_sql;
+
+ INSERT INTO pgl_ddl_deploy.events
+ (set_config_id,
+ set_name,
+ pid,
+ executed_at,
+ ddl_sql_raw,
+ ddl_sql_sent,
+ txid)
+ VALUES
+ (c_set_config_id,
+ c_set_name,
+ v_pid,
+ current_timestamp,
+ v_ddl_sql_raw,
+ v_ddl_sql_sent,
+ v_txid);
+ $BUILD$::TEXT AS shared_deploy_logic,
+ $BUILD$
+ ELSEIF (v_match_count > 0 AND v_cmd_count <> v_match_count) THEN
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'mixed_objects',
+ v_txid);
+ $BUILD$::TEXT AS shared_mixed_obj_logic,
+ $BUILD$
+ -- Filter out purely PG-internal triggers (alas, "pg_event_trigger_dropped_objects" does not expose "tgisinternal", so we must filter by name)
+ -- Also filter out toast tables since if there are any non-toast operations the toast ones are almost certainly internally generated
+ (SELECT * FROM pg_event_trigger_dropped_objects() WHERE address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_a_%' AND address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_c_%' AND schema_name <> 'pg_toast')
+ $BUILD$::TEXT AS dropped_objects_query,
+
+ $BUILD$
+ /**
+ Catch any exceptions and log in a local table
+ As a safeguard, if even the exception handler fails, exit cleanly but add a server log message
+ **/
+ EXCEPTION WHEN OTHERS THEN
+ GET STACKED DIAGNOSTICS
+ v_context = PG_EXCEPTION_CONTEXT,
+ v_error = MESSAGE_TEXT,
+ v_error_detail = PG_EXCEPTION_DETAIL;
+ BEGIN
+ INSERT INTO pgl_ddl_deploy.exceptions (set_config_id, set_name, pid, executed_at, ddl_sql, err_msg, err_state)
+ VALUES (c_set_config_id, c_set_name, v_pid, current_timestamp, v_sql, format('%s %s %s', v_error, v_context, v_error_detail), SQLSTATE);
+ RAISE WARNING '% (%: % - %)', c_exception_msg, v_error, v_context, v_error_detail;
+ --No matter what, don't let this function block any DDL
+ EXCEPTION WHEN OTHERS THEN
+ RAISE WARNING 'Unhandled exception % %', SQLERRM, SQLSTATE;
+ END;
+ $BUILD$::TEXT AS shared_exception_handler,
+
+ $BUILD$
+ FROM pg_namespace n
+ INNER JOIN pg_class c ON n.oid = c.relnamespace
+ AND c.relpersistence = 'p'
+ WHERE n.nspname ~* c_include_schema_regex
+ AND n.nspname !~* c_exclude_always
+ AND EXISTS (SELECT 1
+ FROM pg_index i
+ WHERE i.indrelid = c.oid
+ AND i.indisprimary)
+ AND NOT EXISTS
+ (SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.name = c_set_name
+ AND rsr.relid = c.oid
+ AND rsr.driver = c_driver)
+ $BUILD$::TEXT AS shared_repl_set_tables,
+
+ $BUILD$
+ SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name ~* c_include_schema_regex
+ AND schema_name !~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_include_schema_regex
+ AND object_identity !~* c_exclude_always)
+ )
+ )
+ OR
+ --include_only_repset_tables usage:
+ (
+ ($BUILD$||include_only_repset_tables||$BUILD$) AND
+ (EXISTS
+ (
+ SELECT 1
+ FROM pgl_ddl_deploy.rep_set_table_wrapper() rsr
+ WHERE rsr.relid = c.objid
+ AND c.object_type in('table','table column','table constraint')
+ AND rsr.name = '$BUILD$||sc.set_name||$BUILD$'
+ AND rsr.driver = '$BUILD$||sc.driver||$BUILD$'
+ )
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS match_count,
+ SUM(CASE
+ WHEN
+ --include_everything usage still excludes exclude_always regex:
+ (
+ ($BUILD$||include_everything||$BUILD$) AND
+ (
+ (schema_name ~* c_exclude_always)
+ OR
+ (object_type = 'schema'
+ AND object_identity ~* c_exclude_always)
+ )
+ )
+ THEN 1
+ ELSE 0 END) AS exclude_always_match_count
+ $BUILD$::TEXT AS shared_match_count
+FROM pgl_ddl_deploy.rep_set_wrapper() rs
+INNER JOIN pgl_ddl_deploy.set_configs sc ON sc.set_name = rs.name AND sc.driver = rs.driver
+)
+
+, build AS (
+SELECT
+ id,
+ set_name,
+ include_schema_regex,
+ include_only_repset_tables,
+ include_everything,
+ signal_blocking_subscriber_sessions,
+ subscriber_lock_timeout,
+ auto_replication_create_function_name,
+ auto_replication_drop_function_name,
+ auto_replication_unsupported_function_name,
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name,
+
+CASE WHEN driver = 'pglogical' THEN '--no-op pglogical diver'::TEXT
+WHEN driver = 'native' THEN $BUILD$
+DO $$
+BEGIN
+
+IF NOT EXISTS (SELECT 1
+FROM pg_publication_tables
+WHERE pubname = '$BUILD$||set_name||$BUILD$'
+AND schemaname = 'pgl_ddl_deploy'
+AND tablename = 'queue') THEN
+ ALTER PUBLICATION $BUILD$||quote_ident(set_name)||$BUILD$
+ ADD TABLE pgl_ddl_deploy.queue;
+END IF;
+
+END$$;
+$BUILD$
+END AS add_queue_table_to_replication,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$ || auto_replication_create_function_name || $BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , MAX(c.schema_name)
+ , MAX(cl.relname)
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_nspname, v_relname
+ FROM pg_event_trigger_ddl_commands() c
+ LEFT JOIN LATERAL
+ (SELECT cl.relname
+ FROM pg_class cl
+ WHERE cl.oid = c.objid
+ AND c.classid = (SELECT oid FROM pg_class WHERE relname = 'pg_class')
+ -- There should only be one table modified per event trigger
+ -- At least that's the best we will do now
+ LIMIT 1) cl ON TRUE;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_cmd_count = v_match_count))
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension
+ FROM pg_event_trigger_ddl_commands();
+
+ /**
+ Add table to replication set immediately, if required, and only if the set_config includes CREATE TABLE.
+ We do not filter to tags here, because of possibility of multi-statement SQL.
+ Optional ddl_only_replication will never auto-add tables to replication because the
+ purpose is to only replicate keep the structure synchronized on the subscriber with no data.
+ **/
+ IF c_create_tags && '{"CREATE TABLE"}' AND NOT $BUILD$||include_only_repset_tables||$BUILD$ AND NOT $BUILD$||ddl_only_replication||$BUILD$ THEN
+ PERFORM pgl_ddl_deploy.add_table_to_replication(
+ p_driver:=c_driver
+ ,p_set_name:=c_set_name
+ ,p_relation:=c.oid
+ ,p_synchronize_data:=false
+ )
+ $BUILD$||shared_repl_set_tables||$BUILD$;
+ END IF;
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$::TEXT
+END AS auto_replication_function,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_drop_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ , SUM(CASE
+ WHEN
+ --include_schema_regex usage:
+ (
+ (NOT $BUILD$||include_only_repset_tables||$BUILD$) AND
+ (
+ (schema_name !~* '^(pg_catalog|pg_toast)$'
+ AND schema_name !~* c_include_schema_regex)
+ OR (object_type = 'schema'
+ AND object_identity !~* '^(pg_catalog|pg_toast)$'
+ AND object_identity !~* c_include_schema_regex)
+ )
+ )
+ --include_only_repset_tables cannot be used with DROP because
+ --the objects no longer exist to be checked:
+ THEN 1
+ ELSE 0 END) AS excluded_count
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count, v_excluded_count
+ FROM $BUILD$||dropped_objects_query||$BUILD$ as c;
+
+ $BUILD$||shared_get_query||$BUILD$
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR (v_match_count > 0 AND v_excluded_count = 0))
+
+ THEN
+
+ $BUILD$||shared_deploy_logic||$BUILD$
+
+ INSERT INTO pgl_ddl_deploy.commands
+ (set_config_id,
+ set_name,
+ pid,
+ txid,
+ classid,
+ objid,
+ objsubid,
+ command_tag,
+ object_type,
+ schema_name,
+ object_identity,
+ in_extension)
+ SELECT c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_txid,
+ classid,
+ objid,
+ objsubid,
+ TG_TAG,
+ object_type,
+ schema_name,
+ object_identity,
+ NULL
+ FROM $BUILD$||dropped_objects_query||$BUILD$ as c;
+
+ $BUILD$||shared_mixed_obj_logic||$BUILD$
+
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_drop_function,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE OR REPLACE FUNCTION $BUILD$||auto_replication_unsupported_function_name||$BUILD$() RETURNS EVENT_TRIGGER
+AS
+$BODY$
+DECLARE
+ $BUILD$||declare_constants||$BUILD$
+BEGIN
+
+ /*****
+ Only enter execution body if object being altered is relevant
+ */
+ SELECT COUNT(1)
+ , $BUILD$||shared_match_count||$BUILD$
+ INTO v_cmd_count, v_match_count, v_exclude_always_match_count
+ FROM pg_event_trigger_ddl_commands() c;
+
+ IF ((c_include_everything AND v_exclude_always_match_count = 0) OR v_match_count > 0)
+ THEN
+
+ v_ddl_sql_raw = pgl_ddl_deploy.current_query();
+
+ PERFORM pgl_ddl_deploy.log_unhandled(
+ c_set_config_id,
+ c_set_name,
+ v_pid,
+ v_ddl_sql_raw,
+ TG_TAG,
+ 'unsupported_command',
+ v_txid);
+ END IF;
+
+$BUILD$||shared_exception_handler||$BUILD$
+END;
+$BODY$
+LANGUAGE plpgsql;
+$BUILD$
+END
+ AS auto_replication_unsupported_function,
+
+CASE WHEN create_tags IS NULL THEN '--no-op-null-create-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(create_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$ || auto_replication_create_function_name || $BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_trigger,
+
+CASE WHEN drop_tags IS NULL THEN '--no-op-null-drop-tags'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ON sql_drop
+WHEN TAG IN('$BUILD$||array_to_string(drop_tags,$$','$$)||$BUILD$')
+--TODO - CREATE INDEX HANDLING
+EXECUTE PROCEDURE $BUILD$||auto_replication_drop_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_drop_trigger,
+
+CASE WHEN include_only_repset_tables THEN '--no-op-only-repset-tables'::TEXT ELSE
+$BUILD$
+CREATE EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ON ddl_command_end
+WHEN TAG IN('$BUILD$||array_to_string(pgl_ddl_deploy.unsupported_tags(),$$','$$)||$BUILD$')
+EXECUTE PROCEDURE $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$::TEXT
+END AS auto_replication_unsupported_trigger,
+
+$BUILD$
+DROP TABLE IF EXISTS tmp_objs;
+CREATE TEMP TABLE tmp_objs (obj_type, obj_name) AS (
+VALUES
+('EVENT TRIGGER','$BUILD$||auto_replication_create_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_drop_trigger_name||$BUILD$'),
+('EVENT TRIGGER','$BUILD$||auto_replication_unsupported_trigger_name||$BUILD$'),
+('FUNCTION','$BUILD$||auto_replication_create_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_drop_function_name||$BUILD$()'),
+('FUNCTION','$BUILD$||auto_replication_unsupported_function_name||$BUILD$()')
+);
+
+SELECT pgl_ddl_deploy.drop_ext_object(obj_type, obj_name)
+FROM tmp_objs;
+DROP EVENT TRIGGER IF EXISTS $BUILD$||auto_replication_create_trigger_name||', '||auto_replication_drop_trigger_name||', '||auto_replication_unsupported_trigger_name||$BUILD$;
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_create_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_drop_function_name||$BUILD$();
+DROP FUNCTION IF EXISTS $BUILD$||auto_replication_unsupported_function_name||$BUILD$();
+$BUILD$
+ AS undeploy_sql
+FROM vars)
+
+SELECT
+ b.id,
+ b.set_name,
+ b.include_schema_regex,
+ b.include_only_repset_tables,
+ b.include_everything,
+ b.signal_blocking_subscriber_sessions,
+ b.subscriber_lock_timeout,
+ b.auto_replication_create_function_name,
+ b.auto_replication_drop_function_name,
+ b.auto_replication_unsupported_function_name,
+ b.auto_replication_create_trigger_name,
+ b.auto_replication_drop_trigger_name,
+ b.auto_replication_unsupported_trigger_name,
+ b.auto_replication_function,
+ b.auto_replication_drop_function,
+ b.auto_replication_unsupported_function,
+ b.auto_replication_trigger,
+ b.auto_replication_drop_trigger,
+ b.auto_replication_unsupported_trigger,
+ b.undeploy_sql,
+ b.undeploy_sql||
+ b.add_queue_table_to_replication||$BUILD$
+ $BUILD$||auto_replication_function||$BUILD$
+ $BUILD$||auto_replication_drop_function||$BUILD$
+ $BUILD$||auto_replication_unsupported_function||$BUILD$
+ $BUILD$||auto_replication_trigger||$BUILD$
+ $BUILD$||auto_replication_drop_trigger||$BUILD$
+ $BUILD$||auto_replication_unsupported_trigger||$BUILD$
+ SELECT pgl_ddl_deploy.add_ext_object(obj_type, obj_name)
+ FROM tmp_objs;
+ $BUILD$ AS deploy_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ DISABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ DISABLE;
+ $BUILD$ AS disable_sql,
+ $BUILD$
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_create_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_drop_trigger_name||$BUILD$ ENABLE;
+ ALTER EVENT TRIGGER $BUILD$||auto_replication_unsupported_trigger_name||$BUILD$ ENABLE;
+ $BUILD$ AS enable_sql,
+ EXISTS (SELECT 1
+ FROM pg_event_trigger
+ WHERE evtname IN(
+ auto_replication_create_trigger_name,
+ auto_replication_drop_trigger_name,
+ auto_replication_unsupported_trigger_name
+ )
+ AND evtenabled IN('O','R','A')
+ ) AS is_deployed
+FROM build b;
+
+
diff --git a/pgl_ddl_deploy-sql-maker.sh b/pgl_ddl_deploy-sql-maker.sh
index 4e3d02a..848ccac 100755
--- a/pgl_ddl_deploy-sql-maker.sh
+++ b/pgl_ddl_deploy-sql-maker.sh
@@ -2,8 +2,8 @@
set -eu
-last_version=2.2
-new_version=2.3
+last_version=2.3
+new_version=2.4
last_version_file=pgl_ddl_deploy--${last_version}.sql
new_version_file=pgl_ddl_deploy--${new_version}.sql
update_file=pgl_ddl_deploy--${last_version}--${new_version}.sql
@@ -36,6 +36,10 @@ d=$2
create_update_file_with_header
# Add view and function changes
+add_file schema/2.4.sql $update_file
+add_file functions/common_exclude_alter_table_subcommands.sql $update_file
+add_file functions/rewrite_transaction_safe.sql $update_file
+add_file functions/set_tag_defaults.sql $update_file
add_file views/event_trigger_schema.sql $update_file
# Only copy diff and new files after last version, and add the update script
diff --git a/pgl_ddl_deploy.c b/pgl_ddl_deploy.c
index ca2b52a..6e162f7 100644
--- a/pgl_ddl_deploy.c
+++ b/pgl_ddl_deploy.c
@@ -4,11 +4,15 @@
#include "tcop/utility.h"
#include "utils/builtins.h"
#include "parser/parser.h"
+#include "nodes/nodes.h"
+#include "utils/ruleutils.h"
+#include "postgres_deparse.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(pgl_ddl_deploy_current_query);
PG_FUNCTION_INFO_V1(sql_command_tags);
+PG_FUNCTION_INFO_V1(rewrite_transaction_safe);
/* Our own version of debug_query_string - see below */
const char *pgl_ddl_deploy_debug_query_string;
@@ -84,3 +88,59 @@ sql_command_tags(PG_FUNCTION_ARGS)
PG_RETURN_ARRAYTYPE_P(DatumGetPointer(makeArrayResult(astate, CurrentMemoryContext)));
}
+Datum
+rewrite_transaction_safe(PG_FUNCTION_ARGS)
+{
+
+ text *sql_t = PG_GETARG_TEXT_P(0);
+ char *sql;
+ List *parsetree_list;
+ ListCell *parsetree_item;
+ StringInfoData str;
+ text *result;
+ bool isFirst = true;
+ initStringInfo(&str);
+
+ /*
+ * Get the SQL parsetree
+ */
+ sql = text_to_cstring(sql_t);
+ parsetree_list = pg_parse_query(sql);
+
+ /*
+ * Iterate through each parsetree_item to get CommandTag
+ */
+ foreach(parsetree_item, parsetree_list)
+ {
+ RawStmt *parsetree = (RawStmt *) lfirst(parsetree_item);
+ bool shouldEmit = true;
+ if(IsA(parsetree->stmt, TransactionStmt)) {
+ TransactionStmtKind kind = ((TransactionStmt *) parsetree->stmt)->kind;
+ shouldEmit = kind != TRANS_STMT_BEGIN && kind != TRANS_STMT_START && kind != TRANS_STMT_COMMIT;
+ }
+ if(IsA(parsetree->stmt, IndexStmt)) {
+ IndexStmt *indexStmt = (IndexStmt *) parsetree->stmt;
+ indexStmt->concurrent = false;
+ }
+ if(IsA(parsetree->stmt, DropStmt)) {
+ DropStmt *dropStmt = (DropStmt *) parsetree->stmt;
+ dropStmt->concurrent = false;
+ }
+ if(shouldEmit) {
+ if(!isFirst)
+ {
+ appendStringInfoChar(&str, ' ');
+ }
+ else
+ {
+ isFirst = false;
+ }
+ deparseRawStmt(&str, parsetree);
+ appendStringInfoChar(&str, ';');
+ }
+ }
+ result = cstring_to_text(str.data);
+ pfree(str.data);
+ PG_RETURN_TEXT_P(result);
+}
+
diff --git a/pgl_ddl_deploy.control b/pgl_ddl_deploy.control
index e68a0e3..4f1f1ef 100644
--- a/pgl_ddl_deploy.control
+++ b/pgl_ddl_deploy.control
@@ -1,5 +1,5 @@
# pgl_ddl_deploy extension
comment = 'automated ddl deployment using pglogical'
module_pathname = '$libdir/pgl_ddl_deploy'
-default_version = '2.3'
+default_version = '2.4'
schema = 'pgl_ddl_deploy'
diff --git a/postgres_deparse.11.c b/postgres_deparse.11.c
new file mode 100644
index 0000000..327264b
--- /dev/null
+++ b/postgres_deparse.11.c
@@ -0,0 +1,9887 @@
+#include "pg_config.h"
+#if(PG_VERSION_NUM >= 110000 && PG_VERSION_NUM < 120000)
+
+// Adapted from https://raw.githubusercontent.com/pganalyze/libpg_query/refs/tags/13-2.2.0/src/pg_query_deparse.c
+
+// Copyright (c) 2015, Lukas Fittl
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "postgres.h"
+#include "catalog/index.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_trigger.h"
+#include "commands/trigger.h"
+#include "common/keywords.h"
+#include "lib/stringinfo.h"
+#include "limits.h"
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "utils/builtins.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/xml.h"
+
+typedef enum DeparseNodeContext {
+ DEPARSE_NODE_CONTEXT_NONE,
+ // Parent node type (and sometimes field)
+ DEPARSE_NODE_CONTEXT_INSERT_RELATION,
+ DEPARSE_NODE_CONTEXT_INSERT_ON_CONFLICT,
+ DEPARSE_NODE_CONTEXT_UPDATE,
+ DEPARSE_NODE_CONTEXT_RETURNING,
+ DEPARSE_NODE_CONTEXT_A_EXPR,
+ DEPARSE_NODE_CONTEXT_XMLATTRIBUTES,
+ DEPARSE_NODE_CONTEXT_XMLNAMESPACES,
+ DEPARSE_NODE_CONTEXT_CREATE_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_TYPE,
+ // Identifier vs constant context
+ DEPARSE_NODE_CONTEXT_IDENTIFIER,
+ DEPARSE_NODE_CONTEXT_CONSTANT
+} DeparseNodeContext;
+
+static void
+removeTrailingSpace(StringInfo str)
+{
+ if (str->len >= 1 && str->data[str->len - 1] == ' ') {
+ str->len -= 1;
+ str->data[str->len] = '\0';
+ }
+}
+
+/*
+ * Append a SQL string literal representing "val" to buf.
+ *
+ * Copied here from postgres_fdw/deparse.c to avoid adding
+ * many additional dependencies.
+ */
+static void
+deparseStringLiteral(StringInfo buf, const char *val)
+{
+ const char *valptr;
+
+ /*
+ * Rather than making assumptions about the remote server's value of
+ * standard_conforming_strings, always use E'foo' syntax if there are any
+ * backslashes. This will fail on remote servers before 8.1, but those
+ * are long out of support.
+ */
+ if (strchr(val, '\\') != NULL)
+ appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
+ appendStringInfoChar(buf, '\'');
+ for (valptr = val; *valptr; valptr++)
+ {
+ char ch = *valptr;
+
+ if (SQL_STR_DOUBLE(ch, true))
+ appendStringInfoChar(buf, ch);
+ appendStringInfoChar(buf, ch);
+ }
+ appendStringInfoChar(buf, '\'');
+}
+
+// Check whether the value is a reserved keyword, to determine escaping for output
+//
+// Note that since the parser lowercases all keywords, this does *not* match when the
+// value is not all-lowercase and a reserved keyword.
+static bool
+isReservedKeyword(const char *val)
+{
+ const ScanKeyword *keyword = ScanKeywordLookup(val, ScanKeywords, NumScanKeywords);
+ bool all_lower_case = true;
+ const char *cp;
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ (*cp >= 'a' && *cp <= 'z') ||
+ (*cp >= '0' && *cp <= '9') ||
+ (*cp == '_')))
+ {
+ all_lower_case = false;
+ break;
+ }
+ }
+
+ return all_lower_case && keyword != NULL && keyword->category != UNRESERVED_KEYWORD;
+}
+
+// Returns whether the given value consists only of operator characters
+static bool
+isOp(const char *val)
+{
+ const char *cp;
+
+ Assert(strlen(val) > 0);
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ *cp == '~' ||
+ *cp == '!' ||
+ *cp == '@' ||
+ *cp == '#' ||
+ *cp == '^' ||
+ *cp == '&' ||
+ *cp == '|' ||
+ *cp == '`' ||
+ *cp == '?' ||
+ *cp == '+' ||
+ *cp == '-' ||
+ *cp == '*' ||
+ *cp == '/' ||
+ *cp == '%' ||
+ *cp == '<' ||
+ *cp == '>' ||
+ *cp == '='))
+ return false;
+ }
+
+ return true;
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt);
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause);
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context);
+static void deparseResTarget(StringInfo str, ResTarget *res_target, DeparseNodeContext context);
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt);
+static void deparseAlias(StringInfo str, Alias *alias);
+static void deparseWindowDef(StringInfo str, WindowDef* window_def);
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref);
+static void deparseSubLink(StringInfo str, SubLink* sub_link);
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context);
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr);
+static void deparseAStar(StringInfo str, A_Star* a_star);
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause);
+static void deparseSortBy(StringInfo str, SortBy* sort_by);
+static void deparseParamRef(StringInfo str, ParamRef* param_ref);
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function);
+static void deparseWithClause(StringInfo str, WithClause *with_clause);
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr);
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte);
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect);
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func);
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr * array_expr);
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr);
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast);
+static void deparseTypeName(StringInfo str, TypeName *type_name);
+static void deparseNullTest(StringInfo str, NullTest *null_test);
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr);
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when);
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection);
+static void deparseAIndices(StringInfo str, A_Indices *a_indices);
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr);
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test);
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def);
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt);
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause);
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem);
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt);
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt);
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause);
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default);
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt);
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt);
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter);
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec);
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt);
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt);
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt);
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample);
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func);
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set);
+static void deparseFuncCall(StringInfo str, FuncCall *func_call);
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr);
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr);
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize);
+static void deparseConstraint(StringInfo str, Constraint *constraint);
+static void deparseSchemaStmt(StringInfo str, Node *node);
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt);
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition);
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item);
+static void deparseAConst(StringInfo str, A_Const *a_const);
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr);
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func);
+
+static void deparsePreparableStmt(StringInfo str, Node *node);
+static void deparseRuleActionStmt(StringInfo str, Node *node);
+static void deparseExplainableStmt(StringInfo str, Node *node);
+static void deparseStmt(StringInfo str, Node *node);
+static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context);
+
+// "any_name" in gram.y
+static void deparseAnyName(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, parts)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipFirst(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+ int idx = 0;
+
+ foreach(lc, parts)
+ {
+ if(idx < 1) {
+ idx++;
+ continue;
+ }
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipLast(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+ int idx = 0;
+
+ foreach (lc, parts)
+ {
+ if (lnext(lc))
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (idx < list_length(parts) - 2)
+ appendStringInfoChar(str, '.');
+ }
+ idx++;
+ }
+}
+
+// "a_expr" / "b_expr" in gram.y
+static void deparseExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Expr:
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_NullTest:
+ deparseNullTest(str, castNode(NullTest, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_BoolExpr:
+ deparseBoolExpr(str, castNode(BoolExpr, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_SetToDefault:
+ deparseSetToDefault(str, castNode(SetToDefault, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CollateClause:
+ deparseCollateClause(str, castNode(CollateClause, node));
+ break;
+ case T_CurrentOfExpr:
+ deparseCurrentOfExpr(str, castNode(CurrentOfExpr, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_BooleanTest:
+ deparseBooleanTest(str, castNode(BooleanTest, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "c_expr" in gram.y
+static void deparseCExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_A_Expr:
+ appendStringInfoChar(str, '(');
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ')');
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in c_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "expr_list" in gram.y
+static void deparseExprList(StringInfo str, List *exprs)
+{
+ ListCell *lc;
+
+ foreach(lc, exprs)
+ {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
+static void deparseColId(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "ColLabel", "attr_name"
+//
+// Note this is kept separate from ColId in case we ever want to be more
+// specific on how to handle keywords here
+static void deparseColLabel(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "SignedIconst" and "Iconst" in gram.y
+static void deparseSignedIconst(StringInfo str, Node *node)
+{
+ appendStringInfo(str, "%d", intVal(node));
+}
+
+// "indirection" and "opt_indirection" in gram.y
+static void deparseOptIndirection(StringInfo str, List *indirection, int N)
+{
+ ListCell *lc = NULL;
+ int idx = 0;
+
+ foreach(lc, indirection)
+ {
+ if(idx < N) {
+ idx++;
+ continue;
+ }
+ if (IsA(lfirst(lc), String))
+ {
+ appendStringInfoChar(str, '.');
+ deparseColLabel(str, strVal(lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Star))
+ {
+ appendStringInfoString(str, ".*");
+ }
+ else if (IsA(lfirst(lc), A_Indices))
+ {
+ deparseAIndices(str, castNode(A_Indices, lfirst(lc)));
+ }
+ else
+ {
+ // No other nodes should appear here
+ Assert(false);
+ }
+ }
+}
+
+// "role_list" in gram.y
+static void deparseRoleList(StringInfo str, List *roles)
+{
+ ListCell *lc;
+
+ foreach(lc, roles)
+ {
+ RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
+ deparseRoleSpec(str, role_spec);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SimpleTypename" in gram.y
+static void deparseSimpleTypename(StringInfo str, Node *node)
+{
+ deparseTypeName(str, castNode(TypeName, node));
+}
+
+// "NumericOnly" in gram.y
+static void deparseNumericOnly(StringInfo str, Value *value)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ appendStringInfo(str, "%d", value->val.ival);
+ break;
+ case T_Float:
+ appendStringInfoString(str, value->val.str);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "NumericOnly_list" in gram.y
+static void deparseNumericOnlyList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseNumericOnly(str, (Value *) lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SeqOptElem" in gram.y
+static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseSimpleTypename(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cache") == 0)
+ {
+ appendStringInfoString(str, "CACHE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NO CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "increment") == 0)
+ {
+ appendStringInfoString(str, "INCREMENT ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MAXVALUE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MAXVALUE");
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MINVALUE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MINVALUE");
+ }
+ else if (strcmp(def_elem->defname, "owned_by") == 0)
+ {
+ appendStringInfoString(str, "OWNED BY ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "sequence_name") == 0)
+ {
+ appendStringInfoString(str, "SEQUENCE NAME ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "start") == 0)
+ {
+ appendStringInfoString(str, "START ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "SeqOptList" in gram.y
+static void deparseSeqOptList(StringInfo str, List *options)
+{
+ ListCell *lc;
+ Assert(list_length(options) > 0);
+ foreach (lc, options)
+ {
+ deparseSeqOptElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "OptSeqOptList" in gram.y
+static void deparseOptSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ deparseSeqOptList(str, options);
+}
+
+// "OptParenthesizedSeqOptList" in gram.y
+static void deparseOptParenthesizedSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseSeqOptList(str, options);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "opt_drop_behavior" in gram.y
+static void deparseOptDropBehavior(StringInfo str, DropBehavior behavior)
+{
+ switch (behavior)
+ {
+ case DROP_RESTRICT:
+ // Default
+ break;
+ case DROP_CASCADE:
+ appendStringInfoString(str, "CASCADE ");
+ break;
+ }
+}
+
+// "any_operator" in gram.y
+static void deparseAnyOperator(StringInfo str, List *op)
+{
+ Assert(isOp(strVal(llast(op))));
+ if (list_length(op) == 2)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(linitial(op))));
+ appendStringInfoChar(str, '.');
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else if (list_length(op) == 1)
+ {
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "qual_Op" and "qual_all_Op" in gram.y
+static void deparseQualOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// "subquery_Op" in gram.y
+static void deparseSubqueryOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
+ {
+ appendStringInfoString(str, "LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
+ {
+ appendStringInfoString(str, "NOT LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
+ {
+ appendStringInfoString(str, "ILIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
+ {
+ appendStringInfoString(str, "NOT ILIKE");
+ }
+ else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// Not present directly in gram.y (usually matched by ColLabel)
+static void deparseGenericDefElemName(StringInfo str, const char *in)
+{
+ Assert(in != NULL);
+ char *val = pstrdup(in);
+ for (unsigned char *p = (unsigned char *) val; *p; p++)
+ *p = pg_toupper(*p);
+ appendStringInfoString(str, val);
+ pfree(val);
+}
+
+// "def_arg" and "operator_def_arg" in gram.y
+static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
+{
+ if (IsA(arg, TypeName)) // func_type
+ {
+ deparseTypeName(str, castNode(TypeName, arg));
+ }
+ else if (IsA(arg, List)) // qual_all_Op
+ {
+ List *l = castNode(List, arg);
+ Assert(list_length(l) == 1 || list_length(l) == 2);
+
+ // Schema qualified operator
+ if (list_length(l) == 2)
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, l);
+ appendStringInfoChar(str, ')');
+ }
+ else if (list_length(l) == 1)
+ {
+ appendStringInfoString(str, strVal(linitial(l)));
+ }
+ }
+ else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
+ {
+ deparseValue(str, (Value *) arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (IsA(arg, String))
+ {
+ char *s = strVal(arg);
+ if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) // NONE
+ {
+ appendStringInfoString(str, "NONE");
+ }
+ else if (isReservedKeyword(s)) // reserved_keyword
+ {
+ appendStringInfoString(str, s);
+ }
+ else // Sconst
+ {
+ deparseStringLiteral(str, s);
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "definition" in gram.y
+static void deparseDefinition(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL) {
+ appendStringInfoString(str, " = ");
+ deparseDefArg(str, def_elem->arg, false);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "opt_definition" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptDefinition(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseDefinition(str, options);
+ }
+}
+
+// "create_generic_options" in gram.y
+static void deparseCreateGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ if (options == NULL)
+ return;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "common_func_opt_item" in gram.y
+static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "CALLED ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
+ {
+ appendStringInfoString(str, "IMMUTABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
+ {
+ appendStringInfoString(str, "STABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
+ {
+ appendStringInfoString(str, "VOLATILE");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "SECURITY DEFINER");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "SECURITY INVOKER");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOT LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "cost") == 0)
+ {
+ appendStringInfoString(str, "COST ");
+ deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "rows") == 0)
+ {
+ appendStringInfoString(str, "ROWS ");
+ deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "support") == 0)
+ {
+ appendStringInfoString(str, "SUPPORT ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
+ {
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "parallel") == 0)
+ {
+ appendStringInfoString(str, "PARALLEL ");
+ appendStringInfoString(str, quote_identifier(strVal(def_elem->arg)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "NonReservedWord_or_Sconst" in gram.y
+//
+// Note since both identifiers and string constants are allowed here, we
+// currently always return an identifier, except:
+//
+// 1) when the string is empty (since an empty identifier can't be scanned)
+// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
+static void deparseNonReservedWordOrSconst(StringInfo str, const char *val)
+{
+ if (strlen(val) == 0)
+ appendStringInfoString(str, "''");
+ else if (strlen(val) >= NAMEDATALEN)
+ deparseStringLiteral(str, val);
+ else
+ appendStringInfoString(str, quote_identifier(val));
+}
+
+// "func_as" in gram.y
+static void deparseFuncAs(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ char *strval = strVal(lfirst(lc));
+ if (strstr(strval, "$$") == NULL)
+ {
+ appendStringInfoString(str, "$$");
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, "$$");
+ }
+ else
+ {
+ deparseStringLiteral(str, strval);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createfunc_opt_item" in gram.y
+static void deparseCreateFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc = NULL;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseFuncAs(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "transform") == 0)
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, "TRANSFORM ");
+ foreach (lc, l)
+ {
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ else if (strcmp(def_elem->defname, "window") == 0)
+ {
+ appendStringInfoString(str, "WINDOW");
+ }
+ else
+ {
+ deparseCommonFuncOptItem(str, def_elem);
+ }
+}
+
+// "alter_generic_options" in gram.y
+static void deparseAlterGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ switch (def_elem->defaction)
+ {
+ case DEFELEM_UNSPEC:
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ break;
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "func_name" in gram.y
+static void deparseFuncName(StringInfo str, List *func_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, func_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "function_with_argtypes" in gram.y
+static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ if (!object_with_args->args_unspecified)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, object_with_args->objargs)
+ {
+ if (IsA(lfirst(lc), TypeName))
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ else
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "function_with_argtypes_list" in gram.y
+static void deparseFunctionWithArgtypesList(StringInfo str, List *l)
+{
+ ListCell *lc;
+
+ foreach(lc, l)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "operator_with_argtypes" in gram.y
+static void deparseOperatorWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ deparseAnyOperator(str, object_with_args->objname);
+
+ Assert(list_length(object_with_args->objargs) == 2);
+ appendStringInfoChar(str, '(');
+ if (linitial(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, linitial(object_with_args->objargs)));
+ appendStringInfoString(str, ", ");
+ if (lsecond(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, lsecond(object_with_args->objargs)));
+ appendStringInfoChar(str, ')');
+}
+
+// "aggr_args" in gram.y
+static void deparseAggrArgs(StringInfo str, List *aggr_args)
+{
+ Assert(list_length(aggr_args) == 2);
+
+ ListCell *lc = NULL;
+ List *args = linitial(aggr_args);
+ int order_by_pos = intVal(lsecond(aggr_args));
+ int idx = 0;
+
+ appendStringInfoChar(str, '(');
+ if (args == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, args)
+ {
+ if (idx == order_by_pos)
+ {
+ if (idx > 0)
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, "ORDER BY ");
+ }
+ else if (idx > 0)
+ {
+ appendStringInfoString(str, ", ");
+ }
+
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ idx++;
+ }
+
+ // Repeat the last direct arg as a ordered arg to handle the
+ // simplification done by makeOrderedSetArgs in gram.y
+ if (order_by_pos == list_length(args))
+ {
+ appendStringInfoString(str, " ORDER BY ");
+ deparseFunctionParameter(str, castNode(FunctionParameter, llast(args)));
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "aggregate_with_argtypes" in gram.y
+static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc = NULL;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ appendStringInfoChar(str, '(');
+ if (object_with_args->objargs == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, object_with_args->objargs)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "columnList" in gram.y
+static void deparseColumnList(StringInfo str, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptTemp" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptTemp(StringInfo str, char relpersistence)
+{
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_PERMANENT:
+ // Default
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ appendStringInfoString(str, "UNLOGGED ");
+ break;
+ case RELPERSISTENCE_TEMP:
+ appendStringInfoString(str, "TEMPORARY ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+// "relation_expr_list" in gram.y
+static void deparseRelationExprList(StringInfo str, List *relation_exprs)
+{
+ ListCell *lc = NULL;
+ foreach(lc, relation_exprs)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "handler_name" in gram.y
+static void deparseHandlerName(StringInfo str, List *handler_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, handler_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "fdw_options" in gram.y
+static void deparseFdwOptions(StringInfo str, List *fdw_options)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, fdw_options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO HANDLER ");
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO VALIDATOR ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "type_list" in gram.y
+static void deparseTypeList(StringInfo str, List *type_list)
+{
+ ListCell *lc = NULL;
+ foreach(lc, type_list)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_boolean_or_string" in gram.y
+static void deparseOptBooleanOrString(StringInfo str, char *s)
+{
+ if (s == NULL)
+ return; // No value set
+ else if (strcmp(s, "true") == 0)
+ appendStringInfoString(str, "TRUE");
+ else if (strcmp(s, "false") == 0)
+ appendStringInfoString(str, "FALSE");
+ else if (strcmp(s, "on") == 0)
+ appendStringInfoString(str, "ON");
+ else if (strcmp(s, "off") == 0)
+ appendStringInfoString(str, "OFF");
+ else
+ deparseNonReservedWordOrSconst(str, s);
+}
+
+// "var_name"
+//
+// Note this is kept separate from ColId in case we want to improve the
+// output of namespaced variable names
+static void deparseVarName(StringInfo str, char *s)
+{
+ deparseColId(str, s);
+}
+
+// "var_list"
+static void deparseVarList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, lfirst(lc));
+ if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
+ deparseNumericOnly(str, (Value *) &a_const->val);
+ else if (IsA(&a_const->val, String))
+ deparseOptBooleanOrString(str, strVal(&a_const->val));
+ else
+ Assert(false);
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "transaction_mode_list" in gram.y
+static void deparseTransactionModeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "transaction_isolation") == 0)
+ {
+ char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
+ appendStringInfoString(str, "ISOLATION LEVEL ");
+ if (strcmp(s, "read uncommitted") == 0)
+ appendStringInfoString(str, "READ UNCOMMITTED");
+ else if (strcmp(s, "read committed") == 0)
+ appendStringInfoString(str, "READ COMMITTED");
+ else if (strcmp(s, "repeatable read") == 0)
+ appendStringInfoString(str, "REPEATABLE READ");
+ else if (strcmp(s, "serializable") == 0)
+ appendStringInfoString(str, "SERIALIZABLE");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "READ ONLY");
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "READ WRITE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "DEFERRABLE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "NOT DEFERRABLE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "alter_identity_column_option_list" in gram.y
+static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "generated") == 0)
+ {
+ appendStringInfoString(str, "SET GENERATED ");
+ if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
+ appendStringInfoString(str, "ALWAYS");
+ else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+ appendStringInfoString(str, "BY DEFAULT");
+ else
+ Assert(false);
+ }
+ else
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSeqOptElem(str, def_elem);
+ }
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "reloptions" in gram.y
+static void deparseRelOptions(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (def_elem->defnamespace != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defnamespace));
+ appendStringInfoChar(str, '.');
+ }
+ if (def_elem->defname != NULL)
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->defname != NULL && def_elem->arg != NULL)
+ appendStringInfoChar(str, '=');
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, false);
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "OptWith" and "opt_reloptions" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptWith(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseRelOptions(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "target_list" and "opt_target_list" in gram.y
+static void deparseTargetList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+
+ if (res_target->val == NULL)
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
+ else if (IsA(res_target->val, ColumnRef))
+ deparseColumnRef(str, castNode(ColumnRef, res_target->val));
+ else
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL) {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "insert_column_list" in gram.y
+static void deparseInsertColumnList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->name != NULL);
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ deparseOptIndirection(str, res_target->indirection, 0);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_attribute_list" in gram.y
+static void deparseXmlAttributeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_namespace_list" in gram.y
+static void deparseXmlNamespaceList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (res_target->name == NULL)
+ appendStringInfoString(str, "DEFAULT ");
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "table_ref" in gram.y
+static void deparseTableRef(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_RangeVar:
+ deparseRangeVar(str, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_RangeTableSample:
+ deparseRangeTableSample(str, castNode(RangeTableSample, node));
+ break;
+ case T_RangeFunction:
+ deparseRangeFunction(str, castNode(RangeFunction, node));
+ break;
+ case T_RangeTableFunc:
+ deparseRangeTableFunc(str, castNode(RangeTableFunc, node));
+ break;
+ case T_RangeSubselect:
+ deparseRangeSubselect(str, castNode(RangeSubselect, node));
+ break;
+ case T_JoinExpr:
+ deparseJoinExpr(str, castNode(JoinExpr, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "from_list" in gram.y
+static void deparseFromList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseTableRef(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "from_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseFromClause(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseFromList(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "where_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereClause(StringInfo str, Node *node)
+{
+ if (node != NULL)
+ {
+ appendStringInfoString(str, "WHERE ");
+ deparseExpr(str, node);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "group_by_list" in gram.y
+static void deparseGroupByList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), GroupingSet))
+ deparseGroupingSet(str, castNode(GroupingSet, lfirst(lc)));
+ else
+ deparseExpr(str, lfirst(lc));
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "set_target" in gram.y
+static void deparseSetTarget(StringInfo str, ResTarget *res_target)
+{
+ Assert(res_target->name != NULL);
+ deparseColId(str, res_target->name);
+ deparseOptIndirection(str, res_target->indirection, 0);
+}
+
+// "any_name_list" in gram.y
+static void deparseAnyNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseAnyName(str, castNode(List, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "name_list" in gram.y
+static void deparseNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseColId(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_sort_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptSortClause(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "ORDER BY ");
+
+ foreach(lc, l)
+ {
+ deparseSortBy(str, castNode(SortBy, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "func_arg_expr" in gram.y
+static void deparseFuncArgExpr(StringInfo str, Node *node)
+{
+ if (IsA(node, NamedArgExpr))
+ {
+ NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
+ appendStringInfoString(str, named_arg_expr->name);
+ appendStringInfoString(str, " := ");
+ deparseExpr(str, (Node *) named_arg_expr->arg);
+ }
+ else
+ {
+ deparseExpr(str, node);
+ }
+}
+
+// "set_clause_list" in gram.y
+static void deparseSetClauseList(StringInfo str, List *target_list)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ int skip_next_n_elems = 0;
+ int idx = 0;
+ int idx2 = 0;
+
+ Assert(list_length(target_list) > 0);
+
+ foreach(lc, target_list)
+ {
+ if (skip_next_n_elems > 0)
+ {
+ skip_next_n_elems--;
+ continue;
+ }
+
+ if (idx != 0)
+ appendStringInfoString(str, ", ");
+
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (IsA(res_target->val, MultiAssignRef))
+ {
+ MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
+ appendStringInfoString(str, "(");
+ idx2 = 0;
+ for_each_cell(lc2, lc)
+ {
+ deparseSetTarget(str, castNode(ResTarget, lfirst(lc2)));
+ if (idx2 == r->ncolumns - 1) // Last element in this multi-assign
+ break;
+ else if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ idx2++;
+ }
+ appendStringInfoString(str, ") = ");
+ deparseExpr(str, r->source);
+ skip_next_n_elems = r->ncolumns - 1;
+ }
+ else
+ {
+ deparseSetTarget(str, res_target);
+ appendStringInfoString(str, " = ");
+ deparseExpr(str, res_target->val);
+ }
+ idx++;
+ }
+}
+
+// "func_expr_windowless" in gram.y
+static void deparseFuncExprWindowless(StringInfo str, Node* node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "opt_collate" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptCollate(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "index_elem" in gram.y
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem)
+{
+ if (index_elem->name != NULL)
+ {
+ deparseColId(str, index_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (index_elem->expr != NULL)
+ {
+ switch (nodeTag(index_elem->expr))
+ {
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_TypeCast:
+ case T_CoalesceExpr:
+ case T_MinMaxExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ deparseFuncExprWindowless(str, index_elem->expr);
+ break;
+ default:
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, index_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseOptCollate(str, index_elem->collation);
+
+ if (list_length(index_elem->opclass) > 0)
+ {
+ deparseAnyName(str, index_elem->opclass);
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (index_elem->ordering)
+ {
+ case SORTBY_DEFAULT:
+ // Default
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ // Not allowed in CREATE INDEX
+ Assert(false);
+ break;
+ }
+
+ switch (index_elem->nulls_ordering)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ // Default
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+// "qualified_name_list" in gram.y
+static void deparseQualifiedNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptInherit" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptInherit(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "INHERITS (");
+ deparseQualifiedNameList(str, l);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+// "privilege_target" in gram.y
+static void deparsePrivilegeTarget(StringInfo str, GrantTargetType targtype, ObjectType objtype, List *objs)
+{
+ switch (targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "FOREIGN SERVER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyNameList(str, objs);
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnlyList(str, objs);
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "ALL TABLES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "ALL SEQUENCES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "ALL FUNCTIONS IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "ALL PROCEDURES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ALL ROUTINES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_DEFAULTS: // defacl_privilege_target
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLES");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTIONS");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPES");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMAS");
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ }
+}
+
+// "opclass_item_list" in gram.y
+static void deparseOpclassItemList(StringInfo str, List *items)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, items)
+ {
+ deparseCreateOpClassItem(str, castNode(CreateOpClassItem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createdb_opt_list" in gram.y
+static void deparseCreatedbOptList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "connection_limit") == 0)
+ appendStringInfoString(str, "CONNECTION LIMIT");
+ else
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ appendStringInfoString(str, "DEFAULT");
+ else if (IsA(def_elem->arg, Integer))
+ deparseSignedIconst(str, def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
+{
+ const ListCell *lc = NULL;
+ const ListCell *lc2 = NULL;
+
+ if (stmt->withClause)
+ {
+ deparseWithClause(str, stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (stmt->op) {
+ case SETOP_NONE:
+ if (list_length(stmt->valuesLists) > 0)
+ {
+ const ListCell *lc;
+ appendStringInfoString(str, "VALUES ");
+
+ foreach(lc, stmt->valuesLists)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, lfirst(lc));
+ appendStringInfoChar(str, ')');
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ }
+
+ appendStringInfoString(str, "SELECT ");
+
+ if (list_length(stmt->targetList) > 0)
+ {
+ if (stmt->distinctClause != NULL)
+ {
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
+ {
+ appendStringInfoString(str, "ON (");
+ deparseExprList(str, stmt->distinctClause);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ deparseTargetList(str, stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->intoClause != NULL)
+ {
+ appendStringInfoString(str, "INTO ");
+ deparseOptTemp(str, stmt->intoClause->rel->relpersistence);
+ deparseIntoClause(str, stmt->intoClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, stmt->fromClause);
+ deparseWhereClause(str, stmt->whereClause);
+
+ if (list_length(stmt->groupClause) > 0)
+ {
+ appendStringInfoString(str, "GROUP BY ");
+ deparseGroupByList(str, stmt->groupClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->havingClause != NULL)
+ {
+ appendStringInfoString(str, "HAVING ");
+ deparseExpr(str, stmt->havingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->windowClause != NULL)
+ {
+ appendStringInfoString(str, "WINDOW ");
+ foreach(lc, stmt->windowClause)
+ {
+ WindowDef *window_def = castNode(WindowDef, lfirst(lc));
+ Assert(window_def->name != NULL);
+ appendStringInfoString(str, window_def->name);
+ appendStringInfoString(str, " AS ");
+ deparseWindowDef(str, window_def);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case SETOP_UNION:
+ case SETOP_INTERSECT:
+ case SETOP_EXCEPT:
+ {
+ bool need_larg_parens =
+ list_length(stmt->larg->sortClause) > 0 ||
+ stmt->larg->limitOffset != NULL ||
+ stmt->larg->limitCount != NULL ||
+ list_length(stmt->larg->lockingClause) > 0 ||
+ stmt->larg->withClause != NULL ||
+ stmt->larg->op != SETOP_NONE;
+ bool need_rarg_parens =
+ list_length(stmt->rarg->sortClause) > 0 ||
+ stmt->rarg->limitOffset != NULL ||
+ stmt->rarg->limitCount != NULL ||
+ list_length(stmt->rarg->lockingClause) > 0 ||
+ stmt->rarg->withClause != NULL ||
+ stmt->rarg->op != SETOP_NONE;
+ if (need_larg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->larg);
+ if (need_larg_parens)
+ appendStringInfoChar(str, ')');
+ switch (stmt->op)
+ {
+ case SETOP_UNION:
+ appendStringInfoString(str, " UNION ");
+ break;
+ case SETOP_INTERSECT:
+ appendStringInfoString(str, " INTERSECT ");
+ break;
+ case SETOP_EXCEPT:
+ appendStringInfoString(str, " EXCEPT ");
+ break;
+ default:
+ Assert(false);
+ }
+ if (stmt->all)
+ appendStringInfoString(str, "ALL ");
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ }
+
+ deparseOptSortClause(str, stmt->sortClause);
+
+ if (stmt->limitCount != NULL)
+ {
+ if (IsA(stmt->limitCount, A_Const) && IsA(&castNode(A_Const, stmt->limitCount)->val, Null))
+ appendStringInfoString(str, "ALL");
+ else
+ deparseCExpr(str, stmt->limitCount);
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->limitOffset != NULL)
+ {
+ appendStringInfoString(str, "OFFSET ");
+ deparseExpr(str, stmt->limitOffset);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(stmt->lockingClause) > 0)
+ {
+ foreach(lc, stmt->lockingClause)
+ {
+ deparseLockingClause(str, castNode(LockingClause, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, " ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause)
+{
+ ListCell *lc;
+
+ deparseRangeVar(str, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE); /* target relation name */
+
+ if (list_length(into_clause->colNames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, into_clause->colNames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ deparseOptWith(str, into_clause->options);
+
+ switch (into_clause->onCommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (into_clause->tableSpaceName != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(into_clause->tableSpaceName));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context)
+{
+ if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ONLY ");
+
+ if (range_var->catalogname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->catalogname));
+ appendStringInfoChar(str, '.');
+ }
+
+ if (range_var->schemaname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->schemaname));
+ appendStringInfoChar(str, '.');
+ }
+
+ Assert(range_var->relname != NULL);
+ appendStringInfoString(str, quote_identifier(range_var->relname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_var->alias != NULL)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_var->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt)
+{
+ if (raw_stmt->stmt == NULL)
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
+
+ deparseStmt(str, raw_stmt->stmt);
+}
+
+static void deparseAlias(StringInfo str, Alias *alias)
+{
+ appendStringInfoString(str, quote_identifier(alias->aliasname));
+
+ if (list_length(alias->colnames) > 0)
+ {
+ const ListCell *lc = NULL;
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, alias->colnames);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseAConst(StringInfo str, A_Const *a_const)
+{
+ deparseValue(str, &a_const->val, DEPARSE_NODE_CONTEXT_CONSTANT);
+}
+
+static void deparseFuncCall(StringInfo str, FuncCall *func_call)
+{
+ const ListCell *lc = NULL;
+
+ Assert(list_length(func_call->funcname) > 0);
+
+ if (list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "OVERLAY(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PLACING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ deparseFuncName(str, func_call->funcname);
+ appendStringInfoChar(str, '(');
+
+ if (func_call->agg_distinct)
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (func_call->agg_star)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (list_length(func_call->args) > 0)
+ {
+ foreach(lc, func_call->args)
+ {
+ if (func_call->func_variadic && !lnext(lc))
+ appendStringInfoString(str, "VARIADIC ");
+ deparseFuncArgExpr(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (func_call->agg_order != NULL && !func_call->agg_within_group)
+ {
+ deparseOptSortClause(str, func_call->agg_order);
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+
+ if (func_call->agg_order != NULL && func_call->agg_within_group)
+ {
+ appendStringInfoString(str, "WITHIN GROUP (");
+ deparseOptSortClause(str, func_call->agg_order);
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->agg_filter)
+ {
+ appendStringInfoString(str, "FILTER (WHERE ");
+ deparseExpr(str, func_call->agg_filter);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->over)
+ {
+ appendStringInfoString(str, "OVER ");
+ if (func_call->over->name)
+ appendStringInfoString(str, func_call->over->name);
+ else
+ deparseWindowDef(str, func_call->over);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseWindowDef(StringInfo str, WindowDef* window_def)
+{
+ ListCell *lc;
+
+ // The parent node is responsible for outputting window_def->name
+
+ appendStringInfoChar(str, '(');
+
+ if (window_def->refname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(window_def->refname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(window_def->partitionClause) > 0)
+ {
+ appendStringInfoString(str, "PARTITION BY ");
+ deparseExprList(str, window_def->partitionClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptSortClause(str, window_def->orderClause);
+
+ if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
+ {
+ if (window_def->frameOptions & FRAMEOPTION_RANGE)
+ appendStringInfoString(str, "RANGE ");
+ else if (window_def->frameOptions & FRAMEOPTION_ROWS)
+ appendStringInfoString(str, "ROWS ");
+ else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
+ appendStringInfoString(str, "GROUPS ");
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ appendStringInfoString(str, "BETWEEN ");
+
+ // frame_start
+ if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ {
+ appendStringInfoString(str, "UNBOUNDED PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ {
+ appendStringInfoString(str, "AND ");
+
+ // frame_end
+ if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
+ {
+ appendStringInfoString(str, "UNBOUNDED FOLLOWING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
+ appendStringInfoString(str, "EXCLUDE CURRENT ROW ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
+ appendStringInfoString(str, "EXCLUDE GROUP ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
+ appendStringInfoString(str, "EXCLUDE TIES ");
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref)
+{
+ Assert(list_length(column_ref->fields) >= 1);
+
+ if (IsA(linitial(column_ref->fields), A_Star))
+ deparseAStar(str, castNode(A_Star, linitial(column_ref->fields)));
+ else if (IsA(linitial(column_ref->fields), String))
+ deparseColLabel(str, strVal(linitial(column_ref->fields)));
+
+ deparseOptIndirection(str, column_ref->fields, 1);
+}
+
+static void deparseSubLink(StringInfo str, SubLink* sub_link)
+{
+ switch (sub_link->subLinkType) {
+ case EXISTS_SUBLINK:
+ appendStringInfoString(str, "EXISTS (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ALL_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ALL (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ANY_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ if (list_length(sub_link->operName) > 0)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ANY ");
+ }
+ else
+ {
+ appendStringInfoString(str, " IN ");
+ }
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ROWCOMPARE_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case EXPR_SUBLINK:
+ appendStringInfoString(str, "(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case MULTIEXPR_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case ARRAY_SUBLINK:
+ appendStringInfoString(str, "ARRAY(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case CTE_SUBLINK: /* for SubPlans only */
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context)
+{
+ ListCell *lc;
+ char *name;
+
+ bool need_lexpr_parens = a_expr->lexpr != NULL && (IsA(a_expr->lexpr, BoolExpr) || IsA(a_expr->lexpr, NullTest) || IsA(a_expr->lexpr, A_Expr));
+ bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
+
+ switch (a_expr->kind) {
+ case AEXPR_OP: /* normal operator */
+ {
+ bool need_outer_parens = context == DEPARSE_NODE_CONTEXT_A_EXPR;
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, '(');
+ if (a_expr->lexpr != NULL)
+ {
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ deparseQualOp(str, a_expr->name);
+ if (a_expr->rexpr != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ }
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, ')');
+ }
+ return;
+ case AEXPR_OP_ANY: /* scalar op ANY (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ANY(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OP_ALL: /* scalar op ALL (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ALL(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoString(str, " IS DISTINCT FROM ");
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, " IS NOT DISTINCT FROM ");
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_NULLIF: /* NULLIF - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ appendStringInfoString(str, "NULLIF(");
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OF: /* IS [NOT] OF - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IS OF ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "IS NOT OF ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IN ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "NOT IN ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ if (IsA(a_expr->rexpr, SubLink))
+ deparseSubLink(str, castNode(SubLink, a_expr->rexpr));
+ else
+ deparseExprList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~~") == 0) {
+ appendStringInfoString(str, "LIKE ");
+ } else if (strcmp(name, "!~~") == 0) {
+ appendStringInfoString(str, "NOT LIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~~*") == 0) {
+ appendStringInfoString(str, "ILIKE ");
+ } else if (strcmp(name, "!~~*") == 0) {
+ appendStringInfoString(str, "NOT ILIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~") == 0) {
+ appendStringInfoString(str, "SIMILAR TO ");
+ } else if (strcmp(name, "!~") == 0) {
+ appendStringInfoString(str, "NOT SIMILAR TO ");
+ } else {
+ Assert(false);
+ }
+
+ FuncCall *n = castNode(FuncCall, a_expr->rexpr);
+ Assert(list_length(n->funcname) == 2);
+ Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
+ Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
+ Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
+
+ deparseExpr(str, linitial(n->args));
+ if (list_length(n->args) == 2)
+ {
+ appendStringInfoString(str, " ESCAPE ");
+ deparseExpr(str, lsecond(n->args));
+ }
+
+ return;
+ case AEXPR_BETWEEN: /* name must be "BETWEEN" */
+ case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
+ case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
+ case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, strVal(linitial(a_expr->name)));
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, castNode(List, a_expr->rexpr)) {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case AEXPR_PAREN: /* nameless dummy node for parentheses */
+ // Not present in parse trees when operator_precedence_warning is turned off
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr)
+{
+ const ListCell *lc = NULL;
+ switch (bool_expr->boolop)
+ {
+ case AND_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case OR_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(lc))
+ appendStringInfoString(str, " OR ");
+ }
+ return;
+ case NOT_EXPR:
+ Assert(list_length(bool_expr->args) == 1);
+ bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
+ appendStringInfoString(str, "NOT ");
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(bool_expr->args));
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ }
+}
+
+static void deparseAStar(StringInfo str, A_Star *a_star)
+{
+ appendStringInfoChar(str, '*');
+}
+
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause)
+{
+ ListCell *lc;
+ if (collate_clause->arg != NULL)
+ {
+ bool need_parens = IsA(collate_clause->arg, A_Expr);
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, collate_clause->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, collate_clause->collname);
+}
+
+static void deparseSortBy(StringInfo str, SortBy* sort_by)
+{
+ deparseExpr(str, sort_by->node);
+ appendStringInfoChar(str, ' ');
+
+ switch (sort_by->sortby_dir)
+ {
+ case SORTBY_DEFAULT:
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ appendStringInfoString(str, "USING ");
+ deparseQualOp(str, sort_by->useOp);
+ break;
+ }
+
+ switch (sort_by->sortby_nulls)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseParamRef(StringInfo str, ParamRef* param_ref)
+{
+ if (param_ref->number == 0) {
+ appendStringInfoChar(str, '?');
+ } else {
+ appendStringInfo(str, "$%d", param_ref->number);
+ }
+}
+
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function)
+{
+ switch (sql_value_function->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ appendStringInfoString(str, "current_date");
+ break;
+ case SVFOP_CURRENT_TIME:
+ appendStringInfoString(str, "current_time");
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ appendStringInfoString(str, "current_time"); // with precision
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ appendStringInfoString(str, "current_timestamp");
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ appendStringInfoString(str, "current_timestamp"); // with precision
+ break;
+ case SVFOP_LOCALTIME:
+ appendStringInfoString(str, "localtime");
+ break;
+ case SVFOP_LOCALTIME_N:
+ appendStringInfoString(str, "localtime"); // with precision
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ appendStringInfoString(str, "localtimestamp");
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ appendStringInfoString(str, "localtimestamp"); // with precision
+ break;
+ case SVFOP_CURRENT_ROLE:
+ appendStringInfoString(str, "current_role");
+ break;
+ case SVFOP_CURRENT_USER:
+ appendStringInfoString(str, "current_user");
+ break;
+ case SVFOP_USER:
+ appendStringInfoString(str, "user");
+ break;
+ case SVFOP_SESSION_USER:
+ appendStringInfoString(str, "session_user");
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ appendStringInfoString(str, "current_catalog");
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ appendStringInfoString(str, "current_schema");
+ break;
+ }
+
+ if (sql_value_function->typmod != -1)
+ {
+ appendStringInfo(str, "(%d)", sql_value_function->typmod);
+ }
+}
+
+static void deparseWithClause(StringInfo str, WithClause *with_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "WITH ");
+ if (with_clause->recursive)
+ appendStringInfoString(str, "RECURSIVE ");
+
+ foreach(lc, with_clause->ctes) {
+ deparseCommonTableExpr(str, castNode(CommonTableExpr, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
+{
+ ListCell *lc;
+ bool need_alias_parens = join_expr->alias != NULL;
+ bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
+
+ if (need_alias_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseTableRef(str, join_expr->larg);
+
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->isNatural)
+ appendStringInfoString(str, "NATURAL ");
+
+ switch (join_expr->jointype)
+ {
+ case JOIN_INNER: /* matching tuple pairs only */
+ if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
+ appendStringInfoString(str, "CROSS ");
+ break;
+ case JOIN_LEFT: /* pairs + unmatched LHS tuples */
+ appendStringInfoString(str, "LEFT ");
+ break;
+ case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
+ appendStringInfoString(str, "FULL ");
+ break;
+ case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
+ appendStringInfoString(str, "RIGHT ");
+ break;
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ case JOIN_UNIQUE_OUTER:
+ case JOIN_UNIQUE_INNER:
+ // Only used by the planner/executor, not seen in parser output
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "JOIN ");
+
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseTableRef(str, join_expr->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->quals != NULL)
+ {
+ appendStringInfoString(str, "ON ");
+ deparseExpr(str, join_expr->quals);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(join_expr->usingClause) > 0)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseNameList(str, join_expr->usingClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (need_alias_parens)
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->alias != NULL)
+ deparseAlias(str, join_expr->alias);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
+{
+ deparseColId(str, cte->ctename);
+
+ if (list_length(cte->aliascolnames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, cte->aliascolnames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, cte->ctequery);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
+{
+ if (range_subselect->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, range_subselect->subquery));
+ appendStringInfoChar(str, ')');
+
+ if (range_subselect->alias != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseAlias(str, range_subselect->alias);
+ }
+}
+
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (range_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ if (range_func->is_rowsfrom)
+ {
+ appendStringInfoString(str, "ROWS FROM ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->functions)
+ {
+ List *lfunc = castNode(List, lfirst(lc));
+ Assert(list_length(lfunc) == 2);
+ deparseFuncExprWindowless(str, linitial(lfunc));
+ appendStringInfoChar(str, ' ');
+ List *coldeflist = castNode(List, lsecond(lfunc));
+ if (list_length(coldeflist) > 0)
+ {
+ appendStringInfoString(str, "AS (");
+ foreach(lc2, coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc2)));
+ if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(list_length(linitial(range_func->functions)) == 2);
+ deparseFuncExprWindowless(str, linitial(linitial(range_func->functions)));
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (range_func->ordinality)
+ appendStringInfoString(str, "WITH ORDINALITY ");
+
+ if (range_func->alias != NULL)
+ {
+ deparseAlias(str, range_func->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(range_func->coldeflist) > 0)
+ {
+ if (range_func->alias == NULL)
+ appendStringInfoString(str, "AS ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr *array_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ARRAY[");
+ deparseExprList(str, array_expr->elements);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
+{
+ ListCell *lc;
+
+ switch (row_expr->row_format)
+ {
+ case COERCE_EXPLICIT_CALL:
+ appendStringInfoString(str, "ROW");
+ break;
+ case COERCE_EXPLICIT_CAST:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCE_IMPLICIT_CAST:
+ // No prefix
+ break;
+ }
+
+ appendStringInfoString(str, "(");
+ deparseExprList(str, row_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
+{
+ bool need_parens = false;
+
+ Assert(type_cast->typeName != NULL);
+
+ if (IsA(type_cast->arg, A_Expr))
+ {
+ appendStringInfoString(str, "CAST(");
+ deparseExpr(str, type_cast->arg);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, type_cast->typeName);
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ if (IsA(type_cast->arg, A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, type_cast->arg);
+
+ if (list_length(type_cast->typeName->names) == 2 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
+ {
+ char *typename = strVal(lsecond(type_cast->typeName->names));
+ if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
+ {
+ appendStringInfoString(str, "char ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
+ {
+ /*
+ * Handle "bool" or "false" in the statement, which is represented as a typecast
+ * (other boolean casts should be represented as a cast, i.e. don't need special handling)
+ */
+ char *const_val = strVal(&a_const->val);
+ if (strcmp(const_val, "t") == 0)
+ {
+ appendStringInfoString(str, "true");
+ return;
+ }
+ if (strcmp(const_val, "f") == 0)
+ {
+ appendStringInfoString(str, "false");
+ return;
+ }
+ }
+ }
+
+ // Ensure negative values have wrapping parentheses
+ if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
+ {
+ need_parens = true;
+ }
+ }
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, type_cast->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, "::");
+ deparseTypeName(str, type_cast->typeName);
+}
+
+static void deparseTypeName(StringInfo str, TypeName *type_name)
+{
+ ListCell *lc;
+ bool skip_typmods = false;
+
+ if (type_name->setof)
+ appendStringInfoString(str, "SETOF ");
+
+ if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
+ {
+ const char *name = strVal(lsecond(type_name->names));
+ if (strcmp(name, "bpchar") == 0)
+ {
+ appendStringInfoString(str, "char");
+ }
+ else if (strcmp(name, "varchar") == 0)
+ {
+ appendStringInfoString(str, "varchar");
+ }
+ else if (strcmp(name, "numeric") == 0)
+ {
+ appendStringInfoString(str, "numeric");
+ }
+ else if (strcmp(name, "bool") == 0)
+ {
+ appendStringInfoString(str, "boolean");
+ }
+ else if (strcmp(name, "int2") == 0)
+ {
+ appendStringInfoString(str, "smallint");
+ }
+ else if (strcmp(name, "int4") == 0)
+ {
+ appendStringInfoString(str, "int");
+ }
+ else if (strcmp(name, "int8") == 0)
+ {
+ appendStringInfoString(str, "bigint");
+ }
+ else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
+ {
+ appendStringInfoString(str, "real");
+ }
+ else if (strcmp(name, "float8") == 0)
+ {
+ appendStringInfoString(str, "double precision");
+ }
+ else if (strcmp(name, "time") == 0)
+ {
+ appendStringInfoString(str, "time");
+ }
+ else if (strcmp(name, "timetz") == 0)
+ {
+ appendStringInfoString(str, "time ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "timestamp") == 0)
+ {
+ appendStringInfoString(str, "timestamp");
+ }
+ else if (strcmp(name, "timestamptz") == 0)
+ {
+ appendStringInfoString(str, "timestamp ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
+ {
+ appendStringInfoString(str, "interval");
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
+ {
+ Assert(IsA(linitial(type_name->typmods), A_Const));
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
+
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
+
+ appendStringInfoString(str, "interval");
+
+ // This logic is based on intervaltypmodout in timestamp.c
+ switch (fields)
+ {
+ case INTERVAL_MASK(YEAR):
+ appendStringInfoString(str, " year");
+ break;
+ case INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " month");
+ break;
+ case INTERVAL_MASK(DAY):
+ appendStringInfoString(str, " day");
+ break;
+ case INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " hour");
+ break;
+ case INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " minute");
+ break;
+ case INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " second");
+ break;
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " year to month");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " day to hour");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " day to minute");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " day to second");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " hour to minute");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " hour to second");
+ break;
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " minute to second");
+ break;
+ case INTERVAL_FULL_RANGE:
+ // Nothing
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (list_length(type_name->typmods) == 2)
+ {
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
+ if (precision != INTERVAL_FULL_PRECISION)
+ appendStringInfo(str, "(%d)", precision);
+ }
+
+ skip_typmods = true;
+ }
+ else
+ {
+ appendStringInfoString(str, "pg_catalog.");
+ appendStringInfoString(str, name);
+ }
+ }
+ else
+ {
+ deparseAnyName(str, type_name->names);
+ }
+
+ if (list_length(type_name->typmods) > 0 && !skip_typmods)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ if (IsA(lfirst(lc), A_Const))
+ deparseAConst(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ParamRef))
+ deparseParamRef(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ColumnRef))
+ deparseColumnRef(str, lfirst(lc));
+ else
+ Assert(false);
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ foreach(lc, type_name->arrayBounds)
+ {
+ appendStringInfoChar(str, '[');
+ if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
+ deparseSignedIconst(str, lfirst(lc));
+ appendStringInfoChar(str, ']');
+ }
+
+ if (type_name->pct_type)
+ appendStringInfoString(str, "%type");
+}
+
+static void deparseNullTest(StringInfo str, NullTest *null_test)
+{
+ // argisrow is always false in raw parser output
+ Assert(null_test->argisrow == false);
+
+ deparseExpr(str, (Node *) null_test->arg);
+ switch (null_test->nulltesttype)
+ {
+ case IS_NULL:
+ appendStringInfoString(str, " IS NULL");
+ break;
+ case IS_NOT_NULL:
+ appendStringInfoString(str, " IS NOT NULL");
+ break;
+ }
+}
+
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CASE ");
+
+ if (case_expr->arg != NULL)
+ {
+ deparseExpr(str, (Node *) case_expr->arg);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, case_expr->args)
+ {
+ deparseCaseWhen(str, castNode(CaseWhen, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (case_expr->defresult != NULL)
+ {
+ appendStringInfoString(str, "ELSE ");
+ deparseExpr(str, (Node *) case_expr->defresult);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "END");
+}
+
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when)
+{
+ appendStringInfoString(str, "WHEN ");
+ deparseExpr(str, (Node *) case_when->expr);
+ appendStringInfoString(str, " THEN ");
+ deparseExpr(str, (Node *) case_when->result);
+}
+
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection)
+{
+ ListCell *lc;
+ bool need_parens =
+ IsA(a_indirection->arg, A_Indirection) ||
+ IsA(a_indirection->arg, FuncCall) ||
+ IsA(a_indirection->arg, A_Expr) ||
+ IsA(a_indirection->arg, TypeCast) ||
+ IsA(a_indirection->arg, RowExpr) ||
+ (IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices));
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, a_indirection->arg);
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ deparseOptIndirection(str, a_indirection->indirection, 0);
+}
+
+static void deparseAIndices(StringInfo str, A_Indices *a_indices)
+{
+ appendStringInfoChar(str, '[');
+ if (a_indices->lidx != NULL)
+ deparseExpr(str, a_indices->lidx);
+ if (a_indices->is_slice)
+ appendStringInfoChar(str, ':');
+ if (a_indices->uidx != NULL)
+ deparseExpr(str, a_indices->uidx);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr)
+{
+ appendStringInfoString(str, "COALESCE(");
+ deparseExprList(str, coalesce_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr)
+{
+ switch (min_max_expr->op)
+ {
+ case IS_GREATEST:
+ appendStringInfoString(str, "GREATEST(");
+ break;
+ case IS_LEAST:
+ appendStringInfoString(str, "LEAST(");
+ break;
+ }
+ deparseExprList(str, min_max_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test)
+{
+ deparseExpr(str, (Node *) boolean_test->arg);
+ switch (boolean_test->booltesttype)
+ {
+ case IS_TRUE:
+ appendStringInfoString(str, " IS TRUE");
+ break;
+ case IS_NOT_TRUE:
+ appendStringInfoString(str, " IS NOT TRUE");
+ break;
+ case IS_FALSE:
+ appendStringInfoString(str, " IS FALSE");
+ break;
+ case IS_NOT_FALSE:
+ appendStringInfoString(str, " IS NOT FALSE");
+ break;
+ case IS_UNKNOWN:
+ appendStringInfoString(str, " IS UNKNOWN");
+ break;
+ case IS_NOT_UNKNOWN:
+ appendStringInfoString(str, " IS NOT UNKNOWN");
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
+{
+ ListCell *lc;
+
+ if (column_def->colname != NULL)
+ {
+ appendStringInfoString(str, column_def->colname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->typeName != NULL)
+ {
+ deparseTypeName(str, column_def->typeName);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->raw_default != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseExpr(str, column_def->raw_default);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->fdwoptions != NULL)
+ {
+ deparseCreateGenericOptions(str, column_def->fdwoptions);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, column_def->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->collClause != NULL)
+ {
+ deparseCollateClause(str, column_def->collClause);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (insert_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, insert_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "INSERT INTO ");
+ deparseRangeVar(str, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(insert_stmt->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseInsertColumnList(str, insert_stmt->cols);
+ appendStringInfoString(str, ") ");
+ }
+
+ switch (insert_stmt->override)
+ {
+ case OVERRIDING_NOT_SET:
+ // Do nothing
+ break;
+ case OVERRIDING_USER_VALUE:
+ appendStringInfoString(str, "OVERRIDING USER VALUE ");
+ break;
+ case OVERRIDING_SYSTEM_VALUE:
+ appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
+ break;
+ }
+
+ if (insert_stmt->selectStmt != NULL)
+ {
+ deparseSelectStmt(str, castNode(SelectStmt, insert_stmt->selectStmt));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "DEFAULT VALUES ");
+ }
+
+ if (insert_stmt->onConflictClause != NULL)
+ {
+ deparseOnConflictClause(str, insert_stmt->onConflictClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(insert_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, insert_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInferClause(StringInfo str, InferClause *infer_clause)
+{
+ ListCell *lc;
+
+ if (list_length(infer_clause->indexElems) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, infer_clause->indexElems)
+ {
+ deparseIndexElem(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ if (infer_clause->conname != NULL)
+ {
+ appendStringInfoString(str, "ON CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(infer_clause->conname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, infer_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ON CONFLICT ");
+
+ if (on_conflict_clause->infer != NULL)
+ {
+ deparseInferClause(str, on_conflict_clause->infer);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (on_conflict_clause->action)
+ {
+ case ONCONFLICT_NONE:
+ Assert(false);
+ break;
+ case ONCONFLICT_NOTHING:
+ appendStringInfoString(str, "DO NOTHING ");
+ break;
+ case ONCONFLICT_UPDATE:
+ appendStringInfoString(str, "DO UPDATE ");
+ break;
+ }
+
+ if (list_length(on_conflict_clause->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, on_conflict_clause->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, on_conflict_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
+{
+ ListCell* lc;
+ ListCell* lc2;
+ ListCell* lc3;
+
+ if (update_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, update_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "UPDATE ");
+ deparseRangeVar(str, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(update_stmt->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, update_stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, update_stmt->fromClause);
+ deparseWhereClause(str, update_stmt->whereClause);
+
+ if (list_length(update_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, update_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
+{
+ if (delete_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, delete_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "DELETE FROM ");
+ deparseRangeVar(str, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (delete_stmt->usingClause != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseFromList(str, delete_stmt->usingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, delete_stmt->whereClause);
+
+ if (list_length(delete_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, delete_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause)
+{
+ ListCell *lc;
+
+ switch (locking_clause->strength)
+ {
+ case LCS_NONE:
+ /* no such clause - only used in PlanRowMark */
+ Assert(false);
+ break;
+ case LCS_FORKEYSHARE:
+ appendStringInfoString(str, "FOR KEY SHARE ");
+ break;
+ case LCS_FORSHARE:
+ appendStringInfoString(str, "FOR SHARE ");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ appendStringInfoString(str, "FOR NO KEY UPDATE ");
+ break;
+ case LCS_FORUPDATE:
+ appendStringInfoString(str, "FOR UPDATE ");
+ break;
+ }
+
+ if (list_length(locking_clause->lockedRels) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseQualifiedNameList(str, locking_clause->lockedRels);
+ }
+
+ switch (locking_clause->waitPolicy)
+ {
+ case LockWaitError:
+ appendStringInfoString(str, "NOWAIT");
+ break;
+ case LockWaitSkip:
+ appendStringInfoString(str, "SKIP LOCKED");
+ break;
+ case LockWaitBlock:
+ // Default
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default)
+{
+ appendStringInfoString(str, "DEFAULT");
+}
+
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ appendStringInfoString(str, "CREATE CAST (");
+ deparseTypeName(str, create_cast_stmt->sourcetype);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, create_cast_stmt->targettype);
+ appendStringInfoString(str, ") ");
+
+ if (create_cast_stmt->func != NULL)
+ {
+ appendStringInfoString(str, "WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_cast_stmt->func);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_cast_stmt->inout)
+ {
+ appendStringInfoString(str, "WITH INOUT ");
+ }
+ else
+ {
+ appendStringInfoString(str, "WITHOUT FUNCTION ");
+ }
+
+ switch (create_cast_stmt->context)
+ {
+ case COERCION_IMPLICIT:
+ appendStringInfoString(str, "AS IMPLICIT");
+ break;
+ case COERCION_ASSIGNMENT:
+ appendStringInfoString(str, "AS ASSIGNMENT");
+ break;
+ case COERCION_EXPLICIT:
+ // Default
+ break;
+ }
+}
+
+static void deparseCreateOpClassStmt(StringInfo str, CreateOpClassStmt *create_op_class_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE OPERATOR CLASS ");
+
+ deparseAnyName(str, create_op_class_stmt->opclassname);
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->isDefault)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, create_op_class_stmt->datatype);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_class_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->opfamilyname != NULL)
+ {
+ appendStringInfoString(str, "FAMILY ");
+ deparseAnyName(str, create_op_class_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "AS ");
+ deparseOpclassItemList(str, create_op_class_stmt->items);
+}
+
+static void deparseCreateOpFamilyStmt(StringInfo str, CreateOpFamilyStmt *create_op_family_stmt)
+{
+ appendStringInfoString(str, "CREATE OPERATOR FAMILY ");
+
+ deparseAnyName(str, create_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_family_stmt->amname));
+}
+
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item)
+{
+ ListCell *lc = NULL;
+
+ switch (create_op_class_item->itemtype)
+ {
+ case OPCLASS_ITEM_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+
+ if (create_op_class_item->name != NULL)
+ {
+ if (create_op_class_item->name->objargs != NULL)
+ deparseOperatorWithArgtypes(str, create_op_class_item->name);
+ else
+ deparseAnyOperator(str, create_op_class_item->name->objname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_op_class_item->order_family != NULL)
+ {
+ appendStringInfoString(str, "FOR ORDER BY ");
+ deparseAnyName(str, create_op_class_item->order_family);
+ }
+
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoChar(str, ')');
+ }
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoString(str, ") ");
+ }
+ if (create_op_class_item->name != NULL)
+ deparseFunctionWithArgtypes(str, create_op_class_item->name);
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_STORAGETYPE:
+ appendStringInfoString(str, "STORAGE ");
+ deparseTypeName(str, create_op_class_item->storedtype);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseTableLikeClause(StringInfo str, TableLikeClause *table_like_clause)
+{
+ appendStringInfoString(str, "LIKE ");
+ deparseRangeVar(str, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
+ appendStringInfoString(str, "INCLUDING ALL ");
+ else
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+ appendStringInfoString(str, "INCLUDING COMMENTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ appendStringInfoString(str, "INCLUDING CONSTRAINTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
+ appendStringInfoString(str, "INCLUDING DEFAULTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
+ appendStringInfoString(str, "INCLUDING IDENTITY ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ appendStringInfoString(str, "INCLUDING INDEXES ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
+ appendStringInfoString(str, "INCLUDING STATISTICS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ appendStringInfoString(str, "INCLUDING STORAGE ");
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt)
+{
+ ListCell *lc;
+
+ Assert(create_domain_stmt->typeName != NULL);
+
+ appendStringInfoString(str, "CREATE DOMAIN ");
+ deparseAnyName(str, create_domain_stmt->domainname);
+ appendStringInfoString(str, " AS ");
+
+ deparseTypeName(str, create_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (create_domain_stmt->collClause != NULL)
+ {
+ deparseCollateClause(str, create_domain_stmt->collClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_domain_stmt->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateExtensionStmt(StringInfo str, CreateExtensionStmt *create_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE EXTENSION ");
+
+ if (create_extension_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseColId(str, create_extension_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, create_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "schema") == 0)
+ {
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "cascade") == 0)
+ {
+ appendStringInfoString(str, "CASCADE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraint(StringInfo str, Constraint *constraint)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, constraint->conname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (constraint->contype) {
+ case CONSTR_NULL:
+ appendStringInfoString(str, "NULL ");
+ break;
+ case CONSTR_NOTNULL:
+ appendStringInfoString(str, "NOT NULL ");
+ break;
+ case CONSTR_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, constraint->raw_expr);
+ break;
+ case CONSTR_IDENTITY:
+ appendStringInfoString(str, "GENERATED ");
+ switch (constraint->generated_when)
+ {
+ case ATTRIBUTE_IDENTITY_ALWAYS:
+ appendStringInfoString(str, "ALWAYS ");
+ break;
+ case ATTRIBUTE_IDENTITY_BY_DEFAULT:
+ appendStringInfoString(str, "BY DEFAULT ");
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoString(str, "AS IDENTITY ");
+ deparseOptParenthesizedSeqOptList(str, constraint->options);
+ break;
+ case CONSTR_CHECK:
+ appendStringInfoString(str, "CHECK (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") ");
+ break;
+ case CONSTR_PRIMARY:
+ appendStringInfoString(str, "PRIMARY KEY ");
+ break;
+ case CONSTR_UNIQUE:
+ appendStringInfoString(str, "UNIQUE ");
+ break;
+ case CONSTR_EXCLUSION:
+ appendStringInfoString(str, "EXCLUDE ");
+ if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(constraint->access_method));
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoChar(str, '(');
+ foreach(lc, constraint->exclusions)
+ {
+ List *exclusion = castNode(List, lfirst(lc));
+ Assert(list_length(exclusion) == 2);
+ deparseIndexElem(str, castNode(IndexElem, linitial(exclusion)));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyOperator(str, castNode(List, lsecond(exclusion)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ if (constraint->where_clause != NULL)
+ {
+ appendStringInfoString(str, "WHERE (");
+ deparseExpr(str, constraint->where_clause);
+ appendStringInfoString(str, ") ");
+ }
+ break;
+ case CONSTR_FOREIGN:
+ if (list_length(constraint->fk_attrs) > 0)
+ appendStringInfoString(str, "FOREIGN KEY ");
+ break;
+ case CONSTR_ATTR_DEFERRABLE:
+ appendStringInfoString(str, "DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ appendStringInfoString(str, "NOT DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_DEFERRED:
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+ break;
+ case CONSTR_ATTR_IMMEDIATE:
+ appendStringInfoString(str, "INITIALLY IMMEDIATE ");
+ break;
+ }
+
+ if (list_length(constraint->keys) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->keys);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (list_length(constraint->fk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->fk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->pktable != NULL)
+ {
+ appendStringInfoString(str, "REFERENCES ");
+ deparseRangeVar(str, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ if (list_length(constraint->pk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->pk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ switch (constraint->fk_matchtype)
+ {
+ case FKCONSTR_MATCH_SIMPLE:
+ // Default
+ break;
+ case FKCONSTR_MATCH_FULL:
+ appendStringInfoString(str, "MATCH FULL ");
+ break;
+ case FKCONSTR_MATCH_PARTIAL:
+ // Not implemented in Postgres
+ Assert(false);
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_upd_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON UPDATE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON UPDATE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON UPDATE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON UPDATE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_del_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON DELETE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON DELETE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON DELETE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON DELETE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ if (list_length(constraint->including) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ deparseColumnList(str, constraint->including);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->indexname != NULL)
+ appendStringInfo(str, "USING INDEX %s ", quote_identifier(constraint->indexname));
+
+ if (constraint->indexspace != NULL)
+ appendStringInfo(str, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
+
+ if (constraint->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (constraint->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (constraint->is_no_inherit)
+ appendStringInfoString(str, "NO INHERIT ");
+
+ if (constraint->skip_validation)
+ appendStringInfoString(str, "NOT VALID ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
+{
+ ListCell *lc;
+ bool tableFunc = false;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_function_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_function_stmt->is_procedure)
+ appendStringInfoString(str, "PROCEDURE ");
+ else
+ appendStringInfoString(str, "FUNCTION ");
+
+ deparseFuncName(str, create_function_stmt->funcname);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode != FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(lc) && castNode(FunctionParameter, lfirst(lnext(lc)))->mode != FUNC_PARAM_TABLE)
+ appendStringInfoString(str, ", ");
+ }
+ else
+ {
+ tableFunc = true;
+ }
+ }
+ appendStringInfoString(str, ") ");
+
+ if (tableFunc)
+ {
+ appendStringInfoString(str, "RETURNS TABLE (");
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode == FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_function_stmt->returnType != NULL)
+ {
+ appendStringInfoString(str, "RETURNS ");
+ deparseTypeName(str, create_function_stmt->returnType);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_function_stmt->options)
+ {
+ deparseCreateFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter)
+{
+ switch (function_parameter->mode)
+ {
+ case FUNC_PARAM_IN: /* input only */
+ // Default
+ break;
+ case FUNC_PARAM_OUT: /* output only */
+ appendStringInfoString(str, "OUT ");
+ break;
+ case FUNC_PARAM_INOUT: /* both */
+ appendStringInfoString(str, "INOUT ");
+ break;
+ case FUNC_PARAM_VARIADIC: /* variadic (always input) */
+ appendStringInfoString(str, "VARIADIC ");
+ break;
+ case FUNC_PARAM_TABLE: /* table function output column */
+ // No special annotation, the caller is expected to correctly put
+ // this into the RETURNS part of the CREATE FUNCTION statement
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (function_parameter->name != NULL)
+ {
+ appendStringInfoString(str, function_parameter->name);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseTypeName(str, function_parameter->argType);
+ appendStringInfoChar(str, ' ');
+
+ if (function_parameter->defexpr != NULL)
+ {
+ appendStringInfoString(str, "= ");
+ deparseExpr(str, function_parameter->defexpr);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_stmt)
+{
+ appendStringInfoString(str, "CHECKPOINT");
+}
+
+static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SCHEMA ");
+
+ if (create_schema_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (create_schema_stmt->schemaname)
+ {
+ deparseColId(str, create_schema_stmt->schemaname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->authrole != NULL)
+ {
+ appendStringInfoString(str, "AUTHORIZATION ");
+ deparseRoleSpec(str, create_schema_stmt->authrole);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_schema_stmt->schemaElts)
+ {
+ deparseSchemaStmt(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleSetStmt(StringInfo str, AlterRoleSetStmt *alter_role_set_stmt)
+{
+ appendStringInfoString(str, "ALTER ROLE ");
+
+ if (alter_role_set_stmt->role == NULL)
+ appendStringInfoString(str, "ALL");
+ else
+ deparseRoleSpec(str, alter_role_set_stmt->role);
+
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_set_stmt->database != NULL)
+ {
+ appendStringInfoString(str, "IN DATABASE ");
+ appendStringInfoString(str, quote_identifier(alter_role_set_stmt->database));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseVariableSetStmt(str, alter_role_set_stmt->setstmt);
+}
+
+static void deparseCreateConversionStmt(StringInfo str, CreateConversionStmt *create_conversion_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_conversion_stmt->def)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, create_conversion_stmt->conversion_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "FOR ");
+ deparseStringLiteral(str, create_conversion_stmt->for_encoding_name);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, create_conversion_stmt->to_encoding_name);
+
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, create_conversion_stmt->func_name);
+}
+
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
+{
+ switch (role_spec->roletype)
+ {
+ case ROLESPEC_CSTRING:
+ Assert(role_spec->rolename != NULL);
+ appendStringInfoString(str, quote_identifier(role_spec->rolename));
+ break;
+ case ROLESPEC_CURRENT_USER:
+ appendStringInfoString(str, "CURRENT_USER");
+ break;
+ case ROLESPEC_SESSION_USER:
+ appendStringInfoString(str, "SESSION_USER");
+ break;
+ case ROLESPEC_PUBLIC:
+ appendStringInfoString(str, "public");
+ break;
+ }
+}
+
+// "part_elem" in gram.y
+static void deparsePartitionElem(StringInfo str, PartitionElem *partition_elem)
+{
+ ListCell *lc;
+
+ if (partition_elem->name != NULL)
+ {
+ deparseColId(str, partition_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (partition_elem->expr != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, partition_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptCollate(str, partition_elem->collation);
+ deparseAnyName(str, partition_elem->opclass);
+
+ removeTrailingSpace(str);
+}
+
+static void deparsePartitionSpec(StringInfo str, PartitionSpec *partition_spec)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "PARTITION BY ");
+ appendStringInfoString(str, partition_spec->strategy);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, partition_spec->partParams)
+ {
+ deparsePartitionElem(str, castNode(PartitionElem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparsePartitionBoundSpec(StringInfo str, PartitionBoundSpec *partition_bound_spec)
+{
+ ListCell *lc;
+
+ if (partition_bound_spec->is_default)
+ {
+ appendStringInfoString(str, "DEFAULT");
+ return;
+ }
+
+ appendStringInfoString(str, "FOR VALUES ");
+
+ switch (partition_bound_spec->strategy)
+ {
+ case PARTITION_STRATEGY_HASH:
+ appendStringInfo(str, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
+ break;
+ case PARTITION_STRATEGY_LIST:
+ appendStringInfoString(str, "IN (");
+ deparseExprList(str, partition_bound_spec->listdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ appendStringInfoString(str, "FROM (");
+ deparseExprList(str, partition_bound_spec->lowerdatums);
+ appendStringInfoString(str, ") TO (");
+ deparseExprList(str, partition_bound_spec->upperdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
+{
+ deparseRangeVar(str, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (partition_cmd->bound != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparsePartitionBoundSpec(str, partition_cmd->bound);
+ }
+}
+
+// "TableElement" in gram.y
+static void deparseTableElement(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnDef:
+ deparseColumnDef(str, castNode(ColumnDef, node));
+ break;
+ case T_TableLikeClause:
+ deparseTableLikeClause(str, castNode(TableLikeClause, node));
+ break;
+ case T_Constraint:
+ deparseConstraint(str, castNode(Constraint, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseCreateStmt(StringInfo str, CreateStmt *create_stmt, bool is_foreign_table)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (is_foreign_table)
+ appendStringInfoString(str, "FOREIGN ");
+
+ deparseOptTemp(str, create_stmt->relation->relpersistence);
+
+ appendStringInfoString(str, "TABLE ");
+
+ if (create_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_stmt->ofTypename != NULL)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseTypeName(str, create_stmt->ofTypename);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ Assert(list_length(create_stmt->inhRelations) == 1);
+ appendStringInfoString(str, "PARTITION OF ");
+ deparseRangeVar(str, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(create_stmt->tableElts) > 0)
+ {
+ // In raw parse output tableElts contains both columns and constraints
+ // (and the constraints field is NIL)
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_stmt->tableElts)
+ {
+ deparseTableElement(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
+ {
+ appendStringInfoString(str, "() ");
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ deparsePartitionBoundSpec(str, create_stmt->partbound);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ deparseOptInherit(str, create_stmt->inhRelations);
+ }
+
+ if (create_stmt->partspec != NULL)
+ {
+ deparsePartitionSpec(str, create_stmt->partspec);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptWith(str, create_stmt->options);
+
+ switch (create_stmt->oncommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No ON COMMIT clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (create_stmt->tablespacename != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(create_stmt->tablespacename));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFdwStmt(StringInfo str, CreateFdwStmt *create_fdw_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, create_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseCreateGenericOptions(str, create_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFdwStmt(StringInfo str, AlterFdwStmt *alter_fdw_stmt)
+{
+ appendStringInfoString(str, "ALTER FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(alter_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, alter_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_fdw_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateForeignServerStmt(StringInfo str, CreateForeignServerStmt *create_foreign_server_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SERVER ");
+ if (create_foreign_server_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (create_foreign_server_stmt->servertype != NULL)
+ {
+ appendStringInfoString(str, "TYPE ");
+ deparseStringLiteral(str, create_foreign_server_stmt->servertype);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_foreign_server_stmt->version != NULL)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseStringLiteral(str, create_foreign_server_stmt->version);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterForeignServerStmt(StringInfo str, AlterForeignServerStmt *alter_foreign_server_stmt)
+{
+ appendStringInfoString(str, "ALTER SERVER ");
+
+ appendStringInfoString(str, quote_identifier(alter_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_foreign_server_stmt->has_version)
+ {
+ appendStringInfoString(str, "VERSION ");
+ if (alter_foreign_server_stmt->version != NULL)
+ deparseStringLiteral(str, alter_foreign_server_stmt->version);
+ else
+ appendStringInfoString(str, "NULL");
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_foreign_server_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateUserMappingStmt(StringInfo str, CreateUserMappingStmt *create_user_mapping_stmt)
+{
+ appendStringInfoString(str, "CREATE USER MAPPING ");
+ if (create_user_mapping_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, create_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(create_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreatedbStmt(StringInfo str, CreatedbStmt *createdb_stmt)
+{
+ appendStringInfoString(str, "CREATE DATABASE ");
+ deparseColId(str, createdb_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, createdb_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterUserMappingStmt(StringInfo str, AlterUserMappingStmt *alter_user_mapping_stmt)
+{
+ appendStringInfoString(str, "ALTER USER MAPPING FOR ");
+ deparseRoleSpec(str, alter_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(alter_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseAlterGenericOptions(str, alter_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropUserMappingStmt(StringInfo str, DropUserMappingStmt *drop_user_mapping_stmt)
+{
+ appendStringInfoString(str, "DROP USER MAPPING ");
+
+ if (drop_user_mapping_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, drop_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(drop_user_mapping_stmt->servername));
+}
+
+static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "SECURITY LABEL ");
+
+ if (sec_label_stmt->provider != NULL)
+ {
+ appendStringInfoString(str, "FOR ");
+ appendStringInfoString(str, quote_identifier(sec_label_stmt->provider));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ switch (sec_label_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseValue(str, (Value *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ default:
+ // Not supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (sec_label_stmt->label != NULL)
+ deparseStringLiteral(str, sec_label_stmt->label);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateForeignTableStmt(StringInfo str, CreateForeignTableStmt *create_foreign_table_stmt)
+{
+ ListCell *lc;
+
+ deparseCreateStmt(str, &create_foreign_table_stmt->base, true);
+
+ appendStringInfoString(str, " SERVER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_table_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_foreign_table_stmt->options) > 0)
+ deparseAlterGenericOptions(str, create_foreign_table_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseImportForeignSchemaStmt(StringInfo str, ImportForeignSchemaStmt *import_foreign_schema_stmt)
+{
+ appendStringInfoString(str, "IMPORT FOREIGN SCHEMA ");
+
+ appendStringInfoString(str, import_foreign_schema_stmt->remote_schema);
+ appendStringInfoChar(str, ' ');
+
+ switch (import_foreign_schema_stmt->list_type)
+ {
+ case FDW_IMPORT_SCHEMA_ALL:
+ // Default
+ break;
+ case FDW_IMPORT_SCHEMA_LIMIT_TO:
+ appendStringInfoString(str, "LIMIT TO (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ case FDW_IMPORT_SCHEMA_EXCEPT:
+ appendStringInfoString(str, "EXCEPT (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ }
+
+ appendStringInfoString(str, "FROM SERVER ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->server_name));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "INTO ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->local_schema));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, import_foreign_schema_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_table_as_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
+
+ switch (create_table_as_stmt->relkind)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ if (create_table_as_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseIntoClause(str, create_table_as_stmt->into);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ if (IsA(create_table_as_stmt->query, ExecuteStmt))
+ deparseExecuteStmt(str, castNode(ExecuteStmt, create_table_as_stmt->query));
+ else
+ deparseSelectStmt(str, castNode(SelectStmt, create_table_as_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_as_stmt->into->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (view_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ deparseOptTemp(str, view_stmt->view->relpersistence);
+
+ appendStringInfoString(str, "VIEW ");
+ deparseRangeVar(str, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(view_stmt->aliases) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, view_stmt->aliases);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, view_stmt->options);
+
+ appendStringInfoString(str, "AS ");
+ deparseSelectStmt(str, castNode(SelectStmt, view_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ switch (view_stmt->withCheckOption)
+ {
+ case NO_CHECK_OPTION:
+ // Default
+ break;
+ case LOCAL_CHECK_OPTION:
+ appendStringInfoString(str, "WITH LOCAL CHECK OPTION ");
+ break;
+ case CASCADED_CHECK_OPTION:
+ appendStringInfoString(str, "WITH CHECK OPTION ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "DROP ");
+
+ switch (drop_stmt->removeType)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ default:
+ // Other object types are not supported here in the parser
+ Assert(false);
+ }
+
+ if (drop_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (drop_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (drop_stmt->removeType)
+ {
+ // drop_type_any_name
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ deparseAnyNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name_on_any_name
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseColId(str, strVal(llast(l)));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_CAST:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TRANSFORM:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_LANGUAGE:
+ deparseStringLiteral(str, strVal(linitial(drop_stmt->objects)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_AGGREGATE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPERATOR:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseOptDropBehavior(str, drop_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set)
+{
+ switch(grouping_set->kind)
+ {
+ case GROUPING_SET_EMPTY:
+ appendStringInfoString(str, "()");
+ break;
+ case GROUPING_SET_SIMPLE:
+ // Not present in raw parse trees
+ Assert(false);
+ break;
+ case GROUPING_SET_ROLLUP:
+ appendStringInfoString(str, "ROLLUP (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_CUBE:
+ appendStringInfoString(str, "CUBE (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_SETS:
+ appendStringInfoString(str, "GROUPING SETS (");
+ deparseGroupByList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ }
+}
+
+static void deparseDropTableSpaceStmt(StringInfo str, DropTableSpaceStmt *drop_table_space_stmt)
+{
+ appendStringInfoString(str, "DROP TABLESPACE ");
+
+ if (drop_table_space_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_table_space_stmt->tablespacename);
+}
+
+static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt *alter_object_depends_stmt)
+{
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_depends_stmt->objectType)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ deparseColId(str, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ // No other object types supported here
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "DEPENDS ON EXTENSION ");
+ deparseColId(str, strVal(alter_object_depends_stmt->extname));
+}
+
+static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
+{
+ List *l = NULL;
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_schema_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ appendStringInfoString(str, quote_identifier(strVal(alter_object_schema_stmt->object)));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " SET SCHEMA ");
+ appendStringInfoString(str, quote_identifier(alter_object_schema_stmt->newschema));
+}
+
+static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+ const char *options = NULL;
+ bool trailing_missing_ok = false;
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AddColumn: /* add column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ADD ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ADD COLUMN ");
+ break;
+ case AT_AddColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_ColumnDefault: /* alter column default */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ if (alter_table_cmd->def != NULL)
+ options = "SET DEFAULT";
+ else
+ options = "DROP DEFAULT";
+ break;
+ case AT_DropNotNull: /* alter column drop not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP NOT NULL";
+ break;
+ case AT_SetNotNull: /* alter column set not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET NOT NULL";
+ break;
+ case AT_SetStatistics: /* alter column set statistics */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STATISTICS";
+ break;
+ case AT_SetOptions: /* alter column set ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET";
+ break;
+ case AT_ResetOptions: /* alter column reset ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "RESET";
+ break;
+ case AT_SetStorage: /* alter column set storage */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STORAGE";
+ break;
+ case AT_DropColumn: /* drop column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "DROP ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "DROP ");
+ break;
+ case AT_DropColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndex: /* add index */
+ appendStringInfoString(str, "ADD INDEX ");
+ break;
+ case AT_ReAddIndex: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddConstraint: /* add constraint */
+ appendStringInfoString(str, "ADD ");
+ break;
+ case AT_AddConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ProcessedConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterConstraint: /* alter constraint */
+ appendStringInfoString(str, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
+ break;
+ case AT_ValidateConstraint: /* validate constraint */
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ break;
+ case AT_ValidateConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndexConstraint: /* add constraint using existing index */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropConstraint: /* drop constraint */
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ break;
+ case AT_DropConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddComment: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterColumnType: /* alter column type */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ALTER ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "TYPE";
+ break;
+ case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ // Handled via special case in def handling
+ break;
+ case AT_ChangeOwner: /* change owner */
+ appendStringInfoString(str, "OWNER TO ");
+ deparseRoleSpec(str, alter_table_cmd->newowner);
+ break;
+ case AT_ClusterOn: /* CLUSTER ON */
+ appendStringInfoString(str, "CLUSTER ON ");
+ break;
+ case AT_DropCluster: /* SET WITHOUT CLUSTER */
+ appendStringInfoString(str, "SET WITHOUT CLUSTER ");
+ break;
+ case AT_SetLogged: /* SET LOGGED */
+ appendStringInfoString(str, "SET LOGGED ");
+ break;
+ case AT_SetUnLogged: /* SET UNLOGGED */
+ appendStringInfoString(str, "SET UNLOGGED ");
+ break;
+ case AT_AddOids: /* SET WITH OIDS */
+ appendStringInfoString(str, "SET WITH OIDS ");
+ break;
+ case AT_AddOidsRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_DropOids: /* SET WITHOUT OIDS */
+ appendStringInfoString(str, "SET WITHOUT OIDS ");
+ break;
+ case AT_SetTableSpace: /* SET TABLESPACE */
+ appendStringInfoString(str, "SET TABLESPACE ");
+ break;
+ case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
+ appendStringInfoString(str, "SET ");
+ break;
+ case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
+ appendStringInfoString(str, "RESET ");
+ break;
+ case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_EnableTrig: /* ENABLE TRIGGER name */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
+ appendStringInfoString(str, "ENABLE ALWAYS TRIGGER ");
+ break;
+ case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
+ appendStringInfoString(str, "ENABLE REPLICA TRIGGER ");
+ break;
+ case AT_DisableTrig: /* DISABLE TRIGGER name */
+ appendStringInfoString(str, "DISABLE TRIGGER ");
+ break;
+ case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
+ appendStringInfoString(str, "DISABLE TRIGGER ALL ");
+ break;
+ case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
+ appendStringInfoString(str, "ENABLE TRIGGER USER ");
+ break;
+ case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
+ appendStringInfoString(str, "DISABLE TRIGGER USER ");
+ break;
+ case AT_EnableRule: /* ENABLE RULE name */
+ appendStringInfoString(str, "ENABLE RULE ");
+ break;
+ case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
+ appendStringInfoString(str, "ENABLE ALWAYS RULE ");
+ break;
+ case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
+ appendStringInfoString(str, "ENABLE REPLICA RULE ");
+ break;
+ case AT_DisableRule: /* DISABLE RULE name */
+ appendStringInfoString(str, "DISABLE RULE ");
+ break;
+ case AT_AddInherit: /* INHERIT parent */
+ appendStringInfoString(str, "INHERIT ");
+ break;
+ case AT_DropInherit: /* NO INHERIT parent */
+ appendStringInfoString(str, "NO INHERIT ");
+ break;
+ case AT_AddOf: /* OF */
+ appendStringInfoString(str, "OF ");
+ break;
+ case AT_DropOf: /* NOT OF */
+ appendStringInfoString(str, "NOT OF ");
+ break;
+ case AT_ReplicaIdentity: /* REPLICA IDENTITY */
+ appendStringInfoString(str, "REPLICA IDENTITY ");
+ break;
+ case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
+ appendStringInfoString(str, "ENABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
+ appendStringInfoString(str, "DISABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
+ appendStringInfoString(str, "FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
+ appendStringInfoString(str, "NO FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_GenericOptions: /* OPTIONS (...) */
+ // Handled in def field handling
+ break;
+ case AT_AttachPartition: /* ATTACH PARTITION */
+ appendStringInfoString(str, "ATTACH PARTITION ");
+ break;
+ case AT_DetachPartition: /* DETACH PARTITION */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_AddIdentity: /* ADD IDENTITY */
+ appendStringInfoString(str, "ALTER ");
+ options = "ADD";
+ // Other details are output via the constraint node (in def field)
+ break;
+ case AT_SetIdentity: /* SET identity column options */
+ appendStringInfoString(str, "ALTER ");
+ break;
+ case AT_DropIdentity: /* DROP IDENTITY */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP IDENTITY";
+ trailing_missing_ok = true;
+ break;
+ }
+
+ if (alter_table_cmd->missing_ok && !trailing_missing_ok)
+ {
+ if (alter_table_cmd->subtype == AT_AddColumn)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ else
+ appendStringInfoString(str, "IF EXISTS ");
+ }
+
+ if (alter_table_cmd->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(alter_table_cmd->name));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->num > 0)
+ appendStringInfo(str, "%d ", alter_table_cmd->num);
+
+ if (options != NULL)
+ {
+ appendStringInfoString(str, options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->missing_ok && trailing_missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddColumn:
+ case AT_AlterColumnType:
+ deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ColumnDefault:
+ if (alter_table_cmd->def != NULL)
+ {
+ deparseExpr(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case AT_SetStatistics:
+ deparseSignedIconst(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetOptions:
+ case AT_ResetOptions:
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+ deparseRelOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetStorage:
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddIdentity:
+ case AT_AddConstraint:
+ case AT_AlterConstraint:
+ deparseConstraint(str, castNode(Constraint, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetIdentity:
+ deparseAlterIdentityColumnOptionList(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AlterColumnGenericOptions:
+ case AT_GenericOptions:
+ deparseAlterGenericOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddInherit:
+ case AT_DropInherit:
+ deparseRangeVar(str, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddOf:
+ deparseTypeName(str, castNode(TypeName, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ReplicaIdentity:
+ deparseReplicaIdentityStmt(str, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(alter_table_cmd->def == NULL);
+ break;
+ }
+
+ deparseOptDropBehavior(str, alter_table_cmd->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
+{
+ ListCell *lc;
+ DeparseNodeContext context = DEPARSE_NODE_CONTEXT_NONE;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_table_stmt->relkind)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ context = DEPARSE_NODE_CONTEXT_ALTER_TYPE;
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (alter_table_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_table_stmt->relation, context);
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, alter_table_stmt->cmds)
+ {
+ deparseAlterTableCmd(str, castNode(AlterTableCmd, lfirst(lc)), context);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterTableSpaceOptionsStmt(StringInfo str, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
+{
+ appendStringInfoString(str, "ALTER TABLESPACE ");
+ deparseColId(str, alter_table_space_options_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_table_space_options_stmt->isReset)
+ appendStringInfoString(str, "RESET ");
+ else
+ appendStringInfoString(str, "SET ");
+
+ deparseRelOptions(str, alter_table_space_options_stmt->options);
+}
+
+static void deparseAlterDomainStmt(StringInfo str, AlterDomainStmt *alter_domain_stmt)
+{
+ appendStringInfoString(str, "ALTER DOMAIN ");
+ deparseAnyName(str, alter_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_domain_stmt->subtype)
+ {
+ case 'T':
+ if (alter_domain_stmt->def != NULL)
+ {
+ appendStringInfoString(str, "SET DEFAULT ");
+ deparseExpr(str, alter_domain_stmt->def);
+ }
+ else
+ {
+ appendStringInfoString(str, "DROP DEFAULT");
+ }
+ break;
+ case 'N':
+ appendStringInfoString(str, "DROP NOT NULL");
+ break;
+ case 'O':
+ appendStringInfoString(str, "SET NOT NULL");
+ break;
+ case 'C':
+ appendStringInfoString(str, "ADD ");
+ deparseConstraint(str, castNode(Constraint, alter_domain_stmt->def));
+ break;
+ case 'X':
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ if (alter_domain_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ if (alter_domain_stmt->behavior == DROP_CASCADE)
+ appendStringInfoString(str, " CASCADE");
+ break;
+ case 'V':
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ break;
+ default:
+ // No other subtypes supported by the parser
+ Assert(false);
+ }
+}
+
+static void deparseRenameStmt(StringInfo str, RenameStmt *rename_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_COLUMN:
+ switch (rename_stmt->relationType)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ Assert(false);
+ }
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_ATTRIBUTE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (rename_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, rename_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseColId(str, strVal(rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLUMN:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME COLUMN ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(strVal(rename_stmt->object)));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_DOMAIN:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TYPE:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_ATTRIBUTE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
+ appendStringInfoString(str, " RENAME ATTRIBUTE ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->newname));
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDropBehavior(str, rename_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_stmt)
+{
+ ListCell *lc;
+ switch (transaction_stmt->kind)
+ {
+ case TRANS_STMT_BEGIN:
+ appendStringInfoString(str, "BEGIN ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_START:
+ appendStringInfoString(str, "START TRANSACTION ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_COMMIT:
+ appendStringInfoString(str, "COMMIT ");
+ break;
+ case TRANS_STMT_ROLLBACK:
+ appendStringInfoString(str, "ROLLBACK ");
+ break;
+ case TRANS_STMT_SAVEPOINT:
+ appendStringInfoString(str, "SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_RELEASE:
+ appendStringInfoString(str, "RELEASE ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_ROLLBACK_TO:
+ appendStringInfoString(str, "ROLLBACK ");
+ appendStringInfoString(str, "TO SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_PREPARE:
+ appendStringInfoString(str, "PREPARE TRANSACTION ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_COMMIT_PREPARED:
+ appendStringInfoString(str, "COMMIT PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_ROLLBACK_PREPARED:
+ appendStringInfoString(str, "ROLLBACK PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
+{
+ ListCell *lc;
+
+ switch (variable_set_stmt->kind)
+ {
+ case VAR_SET_VALUE: /* SET var = value */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO ");
+ deparseVarList(str, variable_set_stmt->args);
+ break;
+ case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO DEFAULT");
+ break;
+ case VAR_SET_CURRENT: /* SET var FROM CURRENT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " FROM CURRENT");
+ break;
+ case VAR_SET_MULTI: /* special case for SET TRANSACTION ... */
+ Assert(variable_set_stmt->name != NULL);
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
+ {
+ appendStringInfoString(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION SNAPSHOT ");
+ deparseStringLiteral(str, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case VAR_RESET: /* RESET var */
+ appendStringInfoString(str, "RESET ");
+ deparseVarName(str, variable_set_stmt->name);
+ break;
+ case VAR_RESET_ALL: /* RESET ALL */
+ appendStringInfoString(str, "RESET ALL");
+ break;
+ }
+}
+
+static void deparseDropdbStmt(StringInfo str, DropdbStmt *dropdb_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "DROP DATABASE ");
+ if (dropdb_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, quote_identifier(dropdb_stmt->dbname));
+ appendStringInfoChar(str, ' ');
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+ bool hasAppended = false;
+
+ if (vacuum_stmt->options & VACOPT_VACUUM)
+ appendStringInfoString(str, "VACUUM ");
+ else
+ appendStringInfoString(str, "ANALYZE ");
+
+
+ if (vacuum_stmt->options & VACOPT_VERBOSE)
+
+ if (vacuum_stmt->options & (~VACOPT_ANALYZE) & (~VACOPT_VACUUM))
+ {
+ appendStringInfoChar(str, '(');
+ if ((vacuum_stmt->options & VACOPT_ANALYZE) && (vacuum_stmt->options & VACOPT_VACUUM))
+ {
+ if(hasAppended)
+ {
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, "ANALYZE");
+ hasAppended = true;
+ }
+ if (vacuum_stmt->options & VACOPT_VERBOSE)
+ {
+ if(hasAppended)
+ {
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, "VERBOSE");
+ hasAppended = true;
+ }
+ if (vacuum_stmt->options & VACOPT_FREEZE)
+ {
+ if(hasAppended)
+ {
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, "FREEZE");
+ hasAppended = true;
+ }
+ if (vacuum_stmt->options & VACOPT_FULL)
+ {
+ if(hasAppended)
+ {
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, "FULL");
+ hasAppended = true;
+ }
+ if (vacuum_stmt->options & VACOPT_SKIPTOAST)
+ {
+ if(hasAppended)
+ {
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, "PROCESS_TOAST false");
+ hasAppended = true;
+ }
+ if (vacuum_stmt->options & VACOPT_DISABLE_PAGE_SKIPPING)
+ {
+ if(hasAppended)
+ {
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, "DISABLE_PAGE_SKIPPING");
+ hasAppended = true;
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ foreach(lc, vacuum_stmt->rels)
+ {
+ Assert(IsA(lfirst(lc), VacuumRelation));
+ VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
+
+ deparseRangeVar(str, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(rel->va_cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc2, rel->va_cols)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc2))));
+ if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLoadStmt(StringInfo str, LoadStmt *load_stmt)
+{
+ appendStringInfoString(str, "LOAD ");
+ deparseStringLiteral(str, load_stmt->filename);
+}
+
+static void deparseLockStmt(StringInfo str, LockStmt *lock_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "LOCK TABLE ");
+
+ deparseRelationExprList(str, lock_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (lock_stmt->mode != AccessExclusiveLock)
+ {
+ appendStringInfoString(str, "IN ");
+ switch (lock_stmt->mode)
+ {
+ case AccessShareLock:
+ appendStringInfoString(str, "ACCESS SHARE ");
+ break;
+ case RowShareLock:
+ appendStringInfoString(str, "ROW SHARE ");
+ break;
+ case RowExclusiveLock:
+ appendStringInfoString(str, "ROW EXCLUSIVE ");
+ break;
+ case ShareUpdateExclusiveLock:
+ appendStringInfoString(str, "SHARE UPDATE EXCLUSIVE ");
+ break;
+ case ShareLock:
+ appendStringInfoString(str, "SHARE ");
+ break;
+ case ShareRowExclusiveLock:
+ appendStringInfoString(str, "SHARE ROW EXCLUSIVE ");
+ break;
+ case ExclusiveLock:
+ appendStringInfoString(str, "EXCLUSIVE ");
+ break;
+ case AccessExclusiveLock:
+ appendStringInfoString(str, "ACCESS EXCLUSIVE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+ appendStringInfoString(str, "MODE ");
+ }
+
+ if (lock_stmt->nowait)
+ appendStringInfoString(str, "NOWAIT ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraintsSetStmt(StringInfo str, ConstraintsSetStmt *constraints_set_stmt)
+{
+ appendStringInfoString(str, "SET CONSTRAINTS ");
+
+ if (list_length(constraints_set_stmt->constraints) > 0)
+ {
+ deparseQualifiedNameList(str, constraints_set_stmt->constraints);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ if (constraints_set_stmt->deferred)
+ appendStringInfoString(str, "DEFERRED");
+ else
+ appendStringInfoString(str, "IMMEDIATE");
+}
+
+static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ appendStringInfoString(str, "EXPLAIN ");
+
+ if (list_length(explain_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+
+ foreach(lc, explain_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ if (def_elem->arg != NULL && IsA(def_elem->arg, String))
+ {
+ appendStringInfoChar(str, ' ');
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (def_elem->arg != NULL && (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float)))
+ {
+ appendStringInfoChar(str, ' ');
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseExplainableStmt(str, explain_stmt->query);
+}
+
+static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "COPY ");
+
+ if (copy_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(copy_stmt->attlist) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, copy_stmt->attlist);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (copy_stmt->query != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, copy_stmt->query);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "FROM ");
+ else
+ appendStringInfoString(str, "TO ");
+
+ if (copy_stmt->is_program)
+ appendStringInfoString(str, "PROGRAM ");
+
+ if (copy_stmt->filename != NULL)
+ {
+ deparseStringLiteral(str, copy_stmt->filename);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "STDIN ");
+ else
+ appendStringInfoString(str, "STDOUT ");
+ }
+
+ if (list_length(copy_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "WITH (");
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "format") == 0)
+ {
+ appendStringInfoString(str, "FORMAT ");
+
+ char *format = strVal(def_elem->arg);
+ if (strcmp(format, "binary") == 0)
+ appendStringInfoString(str, "BINARY");
+ else if (strcmp(format, "csv") == 0)
+ appendStringInfoString(str, "CSV");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "freeze") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
+ {
+ appendStringInfoString(str, "FREEZE");
+ if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
+ appendStringInfoString(str, " 1");
+ }
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
+ {
+ appendStringInfoString(str, "DELIMITER ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "null") == 0)
+ {
+ appendStringInfoString(str, "NULL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "header") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
+ {
+ appendStringInfoString(str, "HEADER");
+ if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
+ appendStringInfoString(str, " 1");
+ }
+ else if (strcmp(def_elem->defname, "quote") == 0)
+ {
+ appendStringInfoString(str, "QUOTE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "escape") == 0)
+ {
+ appendStringInfoString(str, "ESCAPE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
+ {
+ appendStringInfoString(str, "FORCE_QUOTE ");
+ if (IsA(def_elem->arg, A_Star))
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NOT_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "force_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "encoding") == 0)
+ {
+ appendStringInfoString(str, "ENCODING ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL)
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ {
+ // Nothing
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ {
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAStar(str, castNode(A_Star, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoChar(str, '(');
+ foreach(lc2, l)
+ {
+ deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
+ if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDoStmt(StringInfo str, DoStmt *do_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DO ");
+
+ foreach (lc, do_stmt->args)
+ {
+ DefElem *defel = castNode(DefElem, lfirst(lc));
+ if (strcmp(defel->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(defel->arg)));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defel->defname, "as") == 0)
+ {
+ char *strval = strVal(defel->arg);
+ const char *delim = "$$";
+ if (strstr(strval, "$$") != NULL)
+ delim = "$outer$";
+ appendStringInfoString(str, delim);
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, delim);
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDiscardStmt(StringInfo str, DiscardStmt *discard_stmt)
+{
+ appendStringInfoString(str, "DISCARD ");
+ switch (discard_stmt->target)
+ {
+ case DISCARD_ALL:
+ appendStringInfoString(str, "ALL");
+ break;
+ case DISCARD_PLANS:
+ appendStringInfoString(str, "PLANS");
+ break;
+ case DISCARD_SEQUENCES:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case DISCARD_TEMP:
+ appendStringInfoString(str, "TEMP");
+ break;
+ }
+}
+
+static void deparseDefineStmt(StringInfo str, DefineStmt *define_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ default:
+ // This shouldn't happen
+ Assert(false);
+ break;
+ }
+
+ if (define_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseFuncName(str, define_stmt->defnames);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAnyOperator(str, define_stmt->defnames);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_COLLATION:
+ deparseAnyName(str, define_stmt->defnames);
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
+ {
+ deparseAggrArgs(str, define_stmt->args);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (define_stmt->kind == OBJECT_COLLATION &&
+ list_length(define_stmt->definition) == 1 &&
+ strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
+ }
+ else if (list_length(define_stmt->definition) > 0)
+ {
+ deparseDefinition(str, define_stmt->definition);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCompositeTypeStmt(StringInfo str, CompositeTypeStmt *composite_type_stmt)
+{
+ ListCell *lc;
+ RangeVar *typevar;
+
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseRangeVar(str, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
+
+ appendStringInfoString(str, " AS (");
+ foreach(lc, composite_type_stmt->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateEnumStmt(StringInfo str, CreateEnumStmt *create_enum_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE TYPE ");
+
+ deparseAnyName(str, create_enum_stmt->typeName);
+ appendStringInfoString(str, " AS ENUM (");
+ foreach(lc, create_enum_stmt->vals)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateRangeStmt(StringInfo str, CreateRangeStmt *create_range_stmt)
+{
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseAnyName(str, create_range_stmt->typeName);
+ appendStringInfoString(str, " AS RANGE ");
+ deparseDefinition(str, create_range_stmt->params);
+}
+
+static void deparseAlterEnumStmt(StringInfo str, AlterEnumStmt *alter_enum_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_enum_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->oldVal == NULL)
+ {
+ appendStringInfoString(str, "ADD VALUE ");
+ if (alter_enum_stmt->skipIfNewValExists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->newValNeighbor)
+ {
+ if (alter_enum_stmt->newValIsAfter)
+ appendStringInfoString(str, "AFTER ");
+ else
+ appendStringInfoString(str, "BEFORE ");
+ deparseStringLiteral(str, alter_enum_stmt->newValNeighbor);
+ }
+ }
+ else
+ {
+ appendStringInfoString(str, "RENAME VALUE ");
+ deparseStringLiteral(str, alter_enum_stmt->oldVal);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionStmt(StringInfo str, AlterExtensionStmt *alter_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_stmt->extname);
+ appendStringInfoString(str, " UPDATE ");
+ foreach (lc, alter_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionContentsStmt(StringInfo str, AlterExtensionContentsStmt *alter_extension_contents_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_contents_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_extension_contents_stmt->action == 1)
+ appendStringInfoString(str, "ADD ");
+ else if (alter_extension_contents_stmt->action == -1)
+ appendStringInfoString(str, "DROP ");
+ else
+ Assert(false);
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ // No other object types are supported here in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ // any_name
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_TABLE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ deparseAnyName(str, castNode(List, alter_extension_contents_stmt->object));
+ break;
+ // name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_LANGUAGE:
+ case OBJECT_SCHEMA:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ deparseColId(str, strVal(alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ deparseTypeName(str, castNode(TypeName, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
+{
+ ListCell *lc;
+
+ if (access_priv->priv_name != NULL)
+ {
+ if (strcmp(access_priv->priv_name, "select") == 0)
+ appendStringInfoString(str, "select");
+ else if (strcmp(access_priv->priv_name, "references") == 0)
+ appendStringInfoString(str, "references");
+ else if (strcmp(access_priv->priv_name, "create") == 0)
+ appendStringInfoString(str, "create");
+ else
+ appendStringInfoString(str, quote_identifier(access_priv->priv_name));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(access_priv->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, access_priv->cols);
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
+{
+ ListCell *lc;
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "GRANT OPTION FOR ");
+
+ if (list_length(grant_stmt->privileges) > 0)
+ {
+ foreach(lc, grant_stmt->privileges)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ deparsePrivilegeTarget(str, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ foreach(lc, grant_stmt->grantees)
+ {
+ deparseRoleSpec(str, castNode(RoleSpec, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "WITH GRANT OPTION ");
+
+ deparseOptDropBehavior(str, grant_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
+{
+ ListCell *lc;
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ foreach(lc, grant_role_stmt->granted_roles)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ deparseRoleList(str, grant_role_stmt->grantee_roles);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_role_stmt->admin_opt)
+ appendStringInfoString(str, "WITH ADMIN OPTION ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropRoleStmt(StringInfo str, DropRoleStmt *drop_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DROP ROLE ");
+
+ if (drop_role_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRoleList(str, drop_role_stmt->roles);
+}
+
+static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (index_stmt->unique)
+ appendStringInfoString(str, "UNIQUE ");
+
+ appendStringInfoString(str, "INDEX ");
+
+ if (index_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (index_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (index_stmt->idxname != NULL)
+ {
+ appendStringInfoString(str, index_stmt->idxname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (index_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(index_stmt->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, index_stmt->indexParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+
+ if (list_length(index_stmt->indexIncludingParams) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ foreach (lc, index_stmt->indexIncludingParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, index_stmt->options);
+
+ if (index_stmt->tableSpace != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(index_stmt->tableSpace));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, index_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterOpFamilyStmt(StringInfo str, AlterOpFamilyStmt *alter_op_family_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR FAMILY ");
+ deparseAnyName(str, alter_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(alter_op_family_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_op_family_stmt->isDrop)
+ appendStringInfoString(str, "DROP ");
+ else
+ appendStringInfoString(str, "ADD ");
+
+ deparseOpclassItemList(str, alter_op_family_stmt->items);
+}
+
+static void deparsePrepareStmt(StringInfo str, PrepareStmt *prepare_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "PREPARE ");
+ deparseColId(str, prepare_stmt->name);
+ if (list_length(prepare_stmt->argtypes) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, prepare_stmt->argtypes);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoString(str, " AS ");
+ deparsePreparableStmt(str, prepare_stmt->query);
+}
+
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "EXECUTE ");
+ appendStringInfoString(str, quote_identifier(execute_stmt->name));
+ if (list_length(execute_stmt->params) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, execute_stmt->params);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseDeallocateStmt(StringInfo str, DeallocateStmt *deallocate_stmt)
+{
+ appendStringInfoString(str, "DEALLOCATE ");
+ if (deallocate_stmt->name != NULL)
+ appendStringInfoString(str, quote_identifier(deallocate_stmt->name));
+ else
+ appendStringInfoString(str, "ALL");
+}
+
+// "AlterOptRoleElem" in gram.y
+static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "password") == 0)
+ {
+ appendStringInfoString(str, "PASSWORD ");
+ if (def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NULL");
+ }
+ else if (IsA(def_elem->arg, ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "connectionlimit") == 0)
+ {
+ appendStringInfo(str, "CONNECTION LIMIT %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validUntil") == 0)
+ {
+ appendStringInfoString(str, "VALID UNTIL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "SUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOSUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOCREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "REPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOREPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOCREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "LOGIN");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOLOGIN");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "BYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOBYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "INHERIT");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOINHERIT");
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "CreateOptRoleElem" in gram.y
+static void deparseCreateRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "sysid") == 0)
+ {
+ appendStringInfo(str, "SYSID %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "adminmembers") == 0)
+ {
+ appendStringInfoString(str, "ADMIN ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "addroleto") == 0)
+ {
+ appendStringInfoString(str, "IN ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ deparseAlterRoleElem(str, def_elem);
+ }
+}
+
+static void deparseCreatePLangStmt(StringInfo str, CreatePLangStmt *create_p_lang_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+
+ if (create_p_lang_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ if (create_p_lang_stmt->pltrusted)
+ appendStringInfoString(str, "TRUSTED ");
+
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, create_p_lang_stmt->plname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_p_lang_stmt->plhandler);
+ appendStringInfoChar(str, ' ');
+
+ if (create_p_lang_stmt->plinline)
+ {
+ appendStringInfoString(str, "INLINE ");
+ deparseHandlerName(str, create_p_lang_stmt->plinline);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_p_lang_stmt->plvalidator)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, create_p_lang_stmt->plvalidator);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateRoleStmt(StringInfo str, CreateRoleStmt *create_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ switch (create_role_stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case ROLESTMT_USER:
+ appendStringInfoString(str, "USER ");
+ break;
+ case ROLESTMT_GROUP:
+ appendStringInfoString(str, "GROUP ");
+ break;
+ }
+
+ appendStringInfoString(str, quote_identifier(create_role_stmt->role));
+ appendStringInfoChar(str, ' ');
+
+ if (create_role_stmt->options != NULL)
+ {
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, create_role_stmt->options)
+ {
+ deparseCreateRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleStmt(StringInfo str, AlterRoleStmt *alter_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "GROUP ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_stmt->action == 1)
+ {
+ appendStringInfoString(str, "ADD USER ");
+ }
+ else if (alter_role_stmt->action == -1)
+ {
+ appendStringInfoString(str, "DROP USER ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseRoleList(str, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, alter_role_stmt->options)
+ {
+ deparseAlterRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeclareCursorStmt(StringInfo str, DeclareCursorStmt *declare_cursor_stmt)
+{
+ appendStringInfoString(str, "DECLARE ");
+ appendStringInfoString(str, quote_identifier(declare_cursor_stmt->portalname));
+ appendStringInfoChar(str, ' ');
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
+ appendStringInfoString(str, "BINARY ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
+ appendStringInfoString(str, "SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
+ appendStringInfoString(str, "NO SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
+ appendStringInfoString(str, "INSENSITIVE ");
+
+ appendStringInfoString(str, "CURSOR ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
+ appendStringInfoString(str, "WITH HOLD ");
+
+ appendStringInfoString(str, "FOR ");
+
+ deparseSelectStmt(str, castNode(SelectStmt, declare_cursor_stmt->query));
+}
+
+static void deparseFetchStmt(StringInfo str, FetchStmt *fetch_stmt)
+{
+ if (fetch_stmt->ismove)
+ appendStringInfoString(str, "MOVE ");
+ else
+ appendStringInfoString(str, "FETCH ");
+
+ switch (fetch_stmt->direction)
+ {
+ case FETCH_FORWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ // Default
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "FORWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_BACKWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "PRIOR ");
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "BACKWARD ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "BACKWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_ABSOLUTE:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "FIRST ");
+ }
+ else if (fetch_stmt->howMany == -1)
+ {
+ appendStringInfoString(str, "LAST ");
+ }
+ else
+ {
+ appendStringInfo(str, "ABSOLUTE %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_RELATIVE:
+ appendStringInfo(str, "RELATIVE %ld ", fetch_stmt->howMany);
+ }
+
+ appendStringInfoString(str, fetch_stmt->portalname);
+}
+
+static void deparseAlterDefaultPrivilegesStmt(StringInfo str, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER DEFAULT PRIVILEGES ");
+
+ foreach (lc, alter_default_privileges_stmt->options)
+ {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp(defelem->defname, "schemas") == 0)
+ {
+ appendStringInfoString(str, "IN SCHEMA ");
+ deparseNameList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defelem->defname, "roles") == 0)
+ {
+ appendStringInfoString(str, "FOR ROLE ");
+ deparseRoleList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ // No other DefElems are supported
+ Assert(false);
+ }
+ }
+
+ deparseGrantStmt(str, alter_default_privileges_stmt->action);
+}
+
+static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
+{
+ appendStringInfoString(str, "REINDEX ");
+
+ if (reindex_stmt->options & REINDEXOPT_VERBOSE)
+ appendStringInfoString(str, "(VERBOSE) ");
+
+ switch (reindex_stmt->kind)
+ {
+ case REINDEX_OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case REINDEX_OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case REINDEX_OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case REINDEX_OBJECT_SYSTEM:
+ appendStringInfoString(str, "SYSTEM ");
+ break;
+ case REINDEX_OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ }
+
+ if (reindex_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (reindex_stmt->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(reindex_stmt->name));
+ }
+}
+
+static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (rule_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "RULE ");
+ appendStringInfoString(str, quote_identifier(rule_stmt->rulename));
+ appendStringInfoString(str, " AS ON ");
+
+ switch (rule_stmt->event)
+ {
+ case CMD_UNKNOWN:
+ case CMD_UTILITY:
+ case CMD_NOTHING:
+ // Not supported here
+ Assert(false);
+ break;
+ case CMD_SELECT:
+ appendStringInfoString(str, "SELECT ");
+ break;
+ case CMD_UPDATE:
+ appendStringInfoString(str, "UPDATE ");
+ break;
+ case CMD_INSERT:
+ appendStringInfoString(str, "INSERT ");
+ break;
+ case CMD_DELETE:
+ appendStringInfoString(str, "DELETE ");
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ deparseRangeVar(str, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseWhereClause(str, rule_stmt->whereClause);
+
+ appendStringInfoString(str, "DO ");
+
+ if (rule_stmt->instead)
+ appendStringInfoString(str, "INSTEAD ");
+
+ if (list_length(rule_stmt->actions) == 0)
+ {
+ appendStringInfoString(str, "NOTHING");
+ }
+ else if (list_length(rule_stmt->actions) == 1)
+ {
+ deparseRuleActionStmt(str, linitial(rule_stmt->actions));
+ }
+ else
+ {
+ appendStringInfoChar(str, '(');
+ foreach (lc, rule_stmt->actions)
+ {
+ deparseRuleActionStmt(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, "; ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseNotifyStmt(StringInfo str, NotifyStmt *notify_stmt)
+{
+ appendStringInfoString(str, "NOTIFY ");
+ appendStringInfoString(str, quote_identifier(notify_stmt->conditionname));
+
+ if (notify_stmt->payload != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseStringLiteral(str, notify_stmt->payload);
+ }
+}
+
+static void deparseListenStmt(StringInfo str, ListenStmt *listen_stmt)
+{
+ appendStringInfoString(str, "LISTEN ");
+ appendStringInfoString(str, quote_identifier(listen_stmt->conditionname));
+}
+
+static void deparseUnlistenStmt(StringInfo str, UnlistenStmt *unlisten_stmt)
+{
+ appendStringInfoString(str, "UNLISTEN ");
+ if (unlisten_stmt->conditionname == NULL)
+ appendStringInfoString(str, "*");
+ else
+ appendStringInfoString(str, quote_identifier(unlisten_stmt->conditionname));
+}
+
+static void deparseCreateSeqStmt(StringInfo str, CreateSeqStmt *create_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_seq_stmt->sequence->relpersistence);
+
+ appendStringInfoString(str, "SEQUENCE ");
+
+ if (create_seq_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptSeqOptList(str, create_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFunctionStmt(StringInfo str, AlterFunctionStmt *alter_function_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_function_stmt->objtype)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ deparseFunctionWithArgtypes(str, alter_function_stmt->func);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, alter_function_stmt->actions)
+ {
+ deparseCommonFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseTruncateStmt(StringInfo str, TruncateStmt *truncate_stmt)
+{
+ appendStringInfoString(str, "TRUNCATE ");
+
+ deparseRelationExprList(str, truncate_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (truncate_stmt->restart_seqs)
+ appendStringInfoString(str, "RESTART IDENTITY ");
+
+ deparseOptDropBehavior(str, truncate_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateEventTrigStmt(StringInfo str, CreateEventTrigStmt *create_event_trig_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "CREATE EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "ON ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->eventname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_event_trig_stmt->whenclause)
+ {
+ appendStringInfoString(str, "WHEN ");
+
+ foreach (lc, create_event_trig_stmt->whenclause)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " IN (");
+ foreach (lc2, l)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc2)));
+ if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ if (lnext(lc))
+ appendStringInfoString(str, " AND ");
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_event_trig_stmt->funcname);
+ appendStringInfoString(str, "()");
+}
+
+static void deparseAlterEventTrigStmt(StringInfo str, AlterEventTrigStmt *alter_event_trig_stmt)
+{
+ appendStringInfoString(str, "ALTER EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(alter_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_event_trig_stmt->tgenabled)
+ {
+ case TRIGGER_FIRES_ON_ORIGIN:
+ appendStringInfoString(str, "ENABLE");
+ break;
+ case TRIGGER_FIRES_ON_REPLICA:
+ appendStringInfoString(str, "ENABLE REPLICA");
+ break;
+ case TRIGGER_FIRES_ALWAYS:
+ appendStringInfoString(str, "ENABLE ALWAYS");
+ break;
+ case TRIGGER_DISABLED:
+ appendStringInfoString(str, "DISABLE");
+ break;
+ }
+}
+
+static void deparseRefreshMatViewStmt(StringInfo str, RefreshMatViewStmt *refresh_mat_view_stmt)
+{
+ appendStringInfoString(str, "REFRESH MATERIALIZED VIEW ");
+
+ if (refresh_mat_view_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ deparseRangeVar(str, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (refresh_mat_view_stmt->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt)
+{
+ switch (replica_identity_stmt->identity_type)
+ {
+ case REPLICA_IDENTITY_NOTHING:
+ appendStringInfoString(str, "NOTHING ");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ appendStringInfoString(str, "FULL ");
+ break;
+ case REPLICA_IDENTITY_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ Assert(replica_identity_stmt->name != NULL);
+ appendStringInfoString(str, "USING INDEX ");
+ appendStringInfoString(str, quote_identifier(replica_identity_stmt->name));
+ break;
+ }
+}
+
+static void deparseCreatePolicyStmt(StringInfo str, CreatePolicyStmt *create_policy_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE POLICY ");
+ deparseColId(str, create_policy_stmt->policy_name);
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (!create_policy_stmt->permissive)
+ appendStringInfoString(str, "AS RESTRICTIVE ");
+
+ if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
+ Assert(true); // Default
+ else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
+ appendStringInfoString(str, "FOR SELECT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
+ appendStringInfoString(str, "FOR INSERT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
+ appendStringInfoString(str, "FOR UPDATE ");
+ else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
+ appendStringInfoString(str, "FOR DELETE ");
+ else
+ Assert(false);
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, create_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ if (create_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, create_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (create_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, create_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseAlterPolicyStmt(StringInfo str, AlterPolicyStmt *alter_policy_stmt)
+{
+ appendStringInfoString(str, "ALTER POLICY ");
+ appendStringInfoString(str, quote_identifier(alter_policy_stmt->policy_name));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_policy_stmt->roles) > 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, alter_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, alter_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (alter_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, alter_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *create_table_space_stmt)
+{
+ appendStringInfoString(str, "CREATE TABLESPACE ");
+ deparseColId(str, create_table_space_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_space_stmt->owner != NULL)
+ {
+ appendStringInfoString(str, "OWNER ");
+ deparseRoleSpec(str, create_table_space_stmt->owner);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "LOCATION ");
+ deparseStringLiteral(str, create_table_space_stmt->location);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptWith(str, create_table_space_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTransformStmt(StringInfo str, CreateTransformStmt *create_transform_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_transform_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "TRANSFORM FOR ");
+ deparseTypeName(str, create_transform_stmt->type_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(create_transform_stmt->lang));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoChar(str, '(');
+
+ if (create_transform_stmt->fromsql)
+ {
+ appendStringInfoString(str, "FROM SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->fromsql);
+ }
+
+ if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
+ appendStringInfoString(str, ", ");
+
+ if (create_transform_stmt->tosql)
+ {
+ appendStringInfoString(str, "TO SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->tosql);
+ }
+
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
+{
+ appendStringInfoString(str, "CREATE ACCESS METHOD ");
+ appendStringInfoString(str, quote_identifier(create_am_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TYPE ");
+ switch (create_am_stmt->amtype)
+ {
+ case AMTYPE_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ }
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_am_stmt->handler_name);
+}
+
+static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_publication_stmt->tables) > 0)
+ {
+ appendStringInfoString(str, "FOR TABLE ");
+ deparseRelationExprList(str, create_publication_stmt->tables);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_publication_stmt->for_all_tables)
+ {
+ appendStringInfoString(str, "FOR ALL TABLES ");
+ }
+
+ deparseOptDefinition(str, create_publication_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *alter_publication_stmt)
+{
+ appendStringInfoString(str, "ALTER PUBLICATION ");
+ deparseColId(str, alter_publication_stmt->pubname);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_publication_stmt->tables) > 0)
+ {
+ switch (alter_publication_stmt->tableAction)
+ {
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET TABLE ");
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD TABLE ");
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP TABLE ");
+ break;
+ case DEFELEM_UNSPEC:
+ Assert(false);
+ break;
+ }
+
+ deparseRelationExprList(str, alter_publication_stmt->tables);
+ }
+ else if (list_length(alter_publication_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_publication_stmt->options);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+static void deparseAlterSeqStmt(StringInfo str, AlterSeqStmt *alter_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SEQUENCE ");
+
+ if (alter_seq_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseSeqOptList(str, alter_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSystemStmt(StringInfo str, AlterSystemStmt *alter_system_stmt)
+{
+ appendStringInfoString(str, "ALTER SYSTEM ");
+ deparseVariableSetStmt(str, alter_system_stmt->setstmt);
+}
+
+static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "COMMENT ON ");
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ deparseAnyName(str, castNode(List, comment_stmt->object));
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(strVal(comment_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ deparseTypeName(str, castNode(TypeName, comment_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON DOMAIN ");
+ deparseTypeName(str, linitial(l));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(lsecond(l))));
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, comment_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseValue(str, (Value *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (comment_stmt->comment != NULL)
+ deparseStringLiteral(str, comment_stmt->comment);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE STATISTICS ");
+
+ if (create_stats_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseAnyName(str, create_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_stats_stmt->stat_types) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, create_stats_stmt->stat_types);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseExprList(str, create_stats_stmt->exprs);
+
+ appendStringInfoString(str, " FROM ");
+ deparseFromList(str, create_stats_stmt->relations);
+}
+
+static void deparseAlterCollationStmt(StringInfo str, AlterCollationStmt *alter_collation_stmt)
+{
+ appendStringInfoString(str, "ALTER COLLATION ");
+ deparseAnyName(str, alter_collation_stmt->collname);
+ appendStringInfoString(str, " REFRESH VERSION");
+}
+
+static void deparseAlterDatabaseStmt(StringInfo str, AlterDatabaseStmt *alter_database_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, alter_database_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterDatabaseSetStmt(StringInfo str, AlterDatabaseSetStmt *alter_database_set_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_set_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseVariableSetStmt(str, alter_database_set_stmt->setstmt);
+}
+
+static void deparseAlterTSDictionaryStmt(StringInfo str, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
+{
+ appendStringInfoString(str, "ALTER TEXT SEARCH DICTIONARY ");
+
+ deparseAnyName(str, alter_ts_dictionary_stmt->dictname);
+ appendStringInfoChar(str, ' ');
+
+ deparseDefinition(str, alter_ts_dictionary_stmt->options);
+}
+
+static void deparseAlterTSConfigurationStmt(StringInfo str, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, alter_ts_configuration_stmt->cfgname);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_ts_configuration_stmt->kind)
+ {
+ case ALTER_TSCONFIG_ADD_MAPPING:
+ appendStringInfoString(str, "ADD MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT:
+ appendStringInfoString(str, "ALTER MAPPING REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_DROP_MAPPING:
+ appendStringInfoString(str, "DROP MAPPING ");
+ if (alter_ts_configuration_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, "FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ break;
+ }
+}
+
+static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_show_stmt)
+{
+ appendStringInfoString(str, "SHOW ");
+
+ if (strcmp(variable_show_stmt->name, "timezone") == 0)
+ appendStringInfoString(str, "TIME ZONE");
+ else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
+ appendStringInfoString(str, "TRANSACTION ISOLATION LEVEL");
+ else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
+ appendStringInfoString(str, "SESSION AUTHORIZATION");
+ else if (strcmp(variable_show_stmt->name, "all") == 0)
+ appendStringInfoString(str, "SESSION ALL");
+ else
+ appendStringInfoString(str, variable_show_stmt->name);
+}
+
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
+{
+ deparseRangeVar(str, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
+
+ appendStringInfoString(str, " TABLESAMPLE ");
+
+ deparseFuncName(str, range_table_sample->method);
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, range_table_sample->args);
+ appendStringInfoString(str, ") ");
+
+ if (range_table_sample->repeatable != NULL)
+ {
+ appendStringInfoString(str, "REPEATABLE (");
+ deparseExpr(str, range_table_sample->repeatable);
+ appendStringInfoString(str, ") ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateSubscriptionStmt(StringInfo str, CreateSubscriptionStmt *create_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(create_subscription_stmt->subname));
+
+ appendStringInfoString(str, " CONNECTION ");
+ if (create_subscription_stmt->conninfo != NULL)
+ deparseStringLiteral(str, create_subscription_stmt->conninfo);
+ else
+ appendStringInfoString(str, "''");
+
+ appendStringInfoString(str, " PUBLICATION ");
+
+ foreach(lc, create_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDefinition(str, create_subscription_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *alter_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(alter_subscription_stmt->subname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_subscription_stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ appendStringInfoString(str, "CONNECTION ");
+ deparseStringLiteral(str, alter_subscription_stmt->conninfo);
+ appendStringInfoChar(str, ' ');
+ break;
+ case ALTER_SUBSCRIPTION_REFRESH:
+ appendStringInfoString(str, "REFRESH PUBLICATION ");
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_PUBLICATION:
+ appendStringInfoString(str, "SET PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ENABLED:
+ Assert(list_length(alter_subscription_stmt->options) == 1);
+ DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
+ Assert(strcmp(defelem->defname, "enabled") == 0);
+ if (intVal(defelem->arg) == 1)
+ {
+ appendStringInfoString(str, " ENABLE ");
+ }
+ else if (intVal(defelem->arg) == 0)
+ {
+ appendStringInfoString(str, " DISABLE ");
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropSubscriptionStmt(StringInfo str, DropSubscriptionStmt *drop_subscription_stmt)
+{
+ appendStringInfoString(str, "DROP SUBSCRIPTION ");
+
+ if (drop_subscription_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_subscription_stmt->subname);
+}
+
+static void deparseCallStmt(StringInfo str, CallStmt *call_stmt)
+{
+ appendStringInfoString(str, "CALL ");
+ deparseFuncCall(str, call_stmt->funccall);
+}
+
+static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_owner_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnly(str, (Value *) alter_owner_stmt->object);
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ default:
+ Assert(false);
+ }
+
+ appendStringInfoString(str, " OWNER TO ");
+ deparseRoleSpec(str, alter_owner_stmt->newowner);
+}
+
+// "operator_def_list" in gram.y
+static void deparseOperatorDefList(StringInfo str, List *defs)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, defs)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " = ");
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, true);
+ else
+ appendStringInfoString(str, "NONE");
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterOperatorStmt(StringInfo str, AlterOperatorStmt *alter_operator_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR ");
+ deparseOperatorWithArgtypes(str, alter_operator_stmt->opername);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_operator_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseDropOwnedStmt(StringInfo str, DropOwnedStmt *drop_owned_stmt)
+{
+ appendStringInfoString(str, "DROP OWNED BY ");
+ deparseRoleList(str, drop_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ deparseOptDropBehavior(str, drop_owned_stmt->behavior);
+ removeTrailingSpace(str);
+}
+
+static void deparseReassignOwnedStmt(StringInfo str, ReassignOwnedStmt *reassigned_owned_stmt)
+{
+ appendStringInfoString(str, "REASSIGN OWNED BY ");
+
+ deparseRoleList(str, reassigned_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleSpec(str, reassigned_owned_stmt->newrole);
+}
+
+static void deparseClosePortalStmt(StringInfo str, ClosePortalStmt *close_portal_stmt)
+{
+ appendStringInfoString(str, "CLOSE ");
+ if (close_portal_stmt->portalname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(close_portal_stmt->portalname));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+}
+
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr)
+{
+ appendStringInfoString(str, "CURRENT OF ");
+ appendStringInfoString(str, quote_identifier(current_of_expr->cursor_name));
+}
+
+static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_stmt)
+{
+ ListCell *lc;
+ bool skip_events_or = true;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_trig_stmt->isconstraint)
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, "TRIGGER ");
+
+ appendStringInfoString(str, quote_identifier(create_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (create_trig_stmt->timing)
+ {
+ case TRIGGER_TYPE_BEFORE:
+ appendStringInfoString(str, "BEFORE ");
+ break;
+ case TRIGGER_TYPE_AFTER:
+ appendStringInfoString(str, "AFTER ");
+ break;
+ case TRIGGER_TYPE_INSTEAD:
+ appendStringInfoString(str, "INSTEAD OF ");
+ break;
+ default:
+ Assert(false);
+ }
+
+ if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
+ {
+ appendStringInfoString(str, "INSERT ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "DELETE ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "UPDATE ");
+ if (list_length(create_trig_stmt->columns) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseColumnList(str, create_trig_stmt->columns);
+ appendStringInfoChar(str, ' ');
+ }
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "TRUNCATE ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_trig_stmt->transitionRels != NULL)
+ {
+ appendStringInfoString(str, "REFERENCING ");
+ foreach(lc, create_trig_stmt->transitionRels)
+ {
+ deparseTriggerTransition(str, castNode(TriggerTransition, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ if (create_trig_stmt->constrrel != NULL)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseRangeVar(str, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_trig_stmt->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (create_trig_stmt->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (create_trig_stmt->row)
+ appendStringInfoString(str, "FOR EACH ROW ");
+
+ if (create_trig_stmt->whenClause)
+ {
+ appendStringInfoString(str, "WHEN (");
+ deparseExpr(str, create_trig_stmt->whenClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_trig_stmt->funcname);
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_trig_stmt->args)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition)
+{
+ if (trigger_transition->isNew)
+ appendStringInfoString(str, "NEW ");
+ else
+ appendStringInfoString(str, "OLD ");
+
+ if (trigger_transition->isTable)
+ appendStringInfoString(str, "TABLE ");
+ else
+ appendStringInfoString(str, "ROW ");
+
+ appendStringInfoString(str, quote_identifier(trigger_transition->name));
+}
+
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
+{
+ switch (xml_expr->op)
+ {
+ case IS_XMLCONCAT: /* XMLCONCAT(args) */
+ appendStringInfoString(str, "xmlconcat(");
+ deparseExprList(str, xml_expr->args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
+ appendStringInfoString(str, "xmlelement(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->named_args != NULL)
+ {
+ appendStringInfoString(str, ", xmlattributes(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoString(str, ")");
+ }
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExprList(str, xml_expr->args);
+ }
+ appendStringInfoString(str, ")");
+ break;
+ case IS_XMLFOREST: /* XMLFOREST(xml_attributes) */
+ appendStringInfoString(str, "xmlforest(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
+ Assert(list_length(xml_expr->args) == 2);
+ appendStringInfoString(str, "xmlparse(");
+ switch (xml_expr->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, linitial(xml_expr->args));
+ if (strcmp(strVal(&castNode(A_Const, castNode(TypeCast, lsecond(xml_expr->args))->arg)->val), "t") == 0)
+ appendStringInfoString(str, " PRESERVE WHITESPACE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPI: /* XMLPI(name [, args]) */
+ appendStringInfoString(str, "xmlpi(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, linitial(xml_expr->args));
+ }
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
+ appendStringInfoString(str, "xmlroot(");
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, ", version ");
+ if (nodeTag(&castNode(A_Const, lsecond(xml_expr->args))->val) == T_Null)
+ appendStringInfoString(str, "NO VALUE");
+ else
+ deparseExpr(str, lsecond(xml_expr->args));
+ if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
+ appendStringInfoString(str, ", STANDALONE YES");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
+ appendStringInfoString(str, ", STANDALONE NO");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
+ appendStringInfoString(str, ", STANDALONE NO VALUE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLSERIALIZE: /* XMLSERIALIZE(is_document, xmlval) */
+ // These are represented as XmlSerialize in raw parse trees
+ Assert(false);
+ break;
+ case IS_DOCUMENT: /* xmlval IS DOCUMENT */
+ Assert(list_length(xml_expr->args) == 1);
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, " IS DOCUMENT");
+ break;
+ }
+}
+
+static void deparseRangeTableFuncCol(StringInfo str, RangeTableFuncCol* range_table_func_col)
+{
+ appendStringInfoString(str, quote_identifier(range_table_func_col->colname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->for_ordinality)
+ {
+ appendStringInfoString(str, "FOR ORDINALITY ");
+ }
+ else
+ {
+ deparseTypeName(str, range_table_func_col->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->colexpr)
+ {
+ appendStringInfoString(str, "PATH ");
+ deparseExpr(str, range_table_func_col->colexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->coldefexpr)
+ {
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, range_table_func_col->coldefexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->is_not_null)
+ appendStringInfoString(str, "NOT NULL ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func)
+{
+ ListCell *lc;
+
+ if (range_table_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoString(str, "xmltable(");
+ if (range_table_func->namespaces)
+ {
+ appendStringInfoString(str, "xmlnamespaces(");
+ deparseXmlNamespaceList(str, range_table_func->namespaces);
+ appendStringInfoString(str, "), ");
+ }
+
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, range_table_func->rowexpr);
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, range_table_func->docexpr);
+
+ appendStringInfoString(str, " COLUMNS ");
+ foreach(lc, range_table_func->columns)
+ {
+ deparseRangeTableFuncCol(str, castNode(RangeTableFuncCol, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, ") ");
+
+ if (range_table_func->alias)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_table_func->alias);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize)
+{
+ appendStringInfoString(str, "xmlserialize(");
+ switch (xml_serialize->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, xml_serialize->expr);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, xml_serialize->typeName);
+ appendStringInfoString(str, ")");
+}
+
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
+{
+ appendStringInfoString(str, "GROUPING(");
+ deparseExprList(str, grouping_func->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
+{
+ appendStringInfoString(str, "CLUSTER ");
+
+ if (cluster_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (cluster_stmt->indexname != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(cluster_stmt->indexname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ case T_Float:
+ deparseNumericOnly(str, value);
+ break;
+ case T_String:
+ if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
+ appendStringInfoString(str, quote_identifier(value->val.str));
+ } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
+ deparseStringLiteral(str, value->val.str);
+ } else {
+ appendStringInfoString(str, value->val.str);
+ }
+ break;
+ case T_BitString:
+ if (strlen(value->val.str) >= 1 && value->val.str[0] == 'x')
+ {
+ appendStringInfoChar(str, 'x');
+ deparseStringLiteral(str, value->val.str + 1);
+ }
+ else if (strlen(value->val.str) >= 1 && value->val.str[0] == 'b')
+ {
+ appendStringInfoChar(str, 'b');
+ deparseStringLiteral(str, value->val.str + 1);
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case T_Null:
+ appendStringInfoString(str, "NULL");
+ break;
+ default:
+ elog(ERROR, "deparse: unrecognized value node type: %d",
+ (int) nodeTag(value));
+ break;
+ }
+}
+
+// "PrepareableStmt" in gram.y
+static void deparsePreparableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "RuleActionStmt" in gram.y
+static void deparseRuleActionStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "ExplainableStmt" in gram.y
+static void deparseExplainableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_CreateTableAsStmt:
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "schema_stmt" in gram.y
+static void deparseSchemaStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "stmt" in gram.y
+static void deparseStmt(StringInfo str, Node *node)
+{
+ // Note the following grammar names are missing in the list, because they
+ // get mapped to other node types:
+ //
+ // - AlterForeignTableStmt (=> AlterTableStmt)
+ // - AlterGroupStmt (=> AlterRoleStmt)
+ // - AlterCompositeTypeStmt (=> AlterTableStmt)
+ // - AnalyzeStmt (=> VacuumStmt)
+ // - CreateGroupStmt (=> CreateRoleStmt)
+ // - CreateMatViewStmt (=> CreateTableAsStmt)
+ // - CreateUserStmt (=> CreateRoleStmt)
+ // - DropCastStmt (=> DropStmt)
+ // - DropOpClassStmt (=> DropStmt)
+ // - DropOpFamilyStmt (=> DropStmt)
+ // - DropPLangStmt (=> DropPLangStmt)
+ // - DropTransformStmt (=> DropStmt)
+ // - RemoveAggrStmt (=> DropStmt)
+ // - RemoveFuncStmt (=> DropStmt)
+ // - RemoveOperStmt (=> DropStmt)
+ // - RevokeStmt (=> GrantStmt)
+ // - RevokeRoleStmt (=> GrantRoleStmt)
+ // - VariableResetStmt (=> VariableSetStmt)
+ //
+ // And the following grammar names error out in the parser:
+ // - CreateAssertionStmt (not supported yet)
+ switch (nodeTag(node))
+ {
+ case T_AlterEventTrigStmt:
+ deparseAlterEventTrigStmt(str, castNode(AlterEventTrigStmt, node));
+ break;
+ case T_AlterCollationStmt:
+ deparseAlterCollationStmt(str, castNode(AlterCollationStmt, node));
+ break;
+ case T_AlterDatabaseStmt:
+ deparseAlterDatabaseStmt(str, castNode(AlterDatabaseStmt, node));
+ break;
+ case T_AlterDatabaseSetStmt:
+ deparseAlterDatabaseSetStmt(str, castNode(AlterDatabaseSetStmt, node));
+ break;
+ case T_AlterDefaultPrivilegesStmt:
+ deparseAlterDefaultPrivilegesStmt(str, castNode(AlterDefaultPrivilegesStmt, node));
+ break;
+ case T_AlterDomainStmt:
+ deparseAlterDomainStmt(str, castNode(AlterDomainStmt, node));
+ break;
+ case T_AlterEnumStmt:
+ deparseAlterEnumStmt(str, castNode(AlterEnumStmt, node));
+ break;
+ case T_AlterExtensionStmt:
+ deparseAlterExtensionStmt(str, castNode(AlterExtensionStmt, node));
+ break;
+ case T_AlterExtensionContentsStmt:
+ deparseAlterExtensionContentsStmt(str, castNode(AlterExtensionContentsStmt, node));
+ break;
+ case T_AlterFdwStmt:
+ deparseAlterFdwStmt(str, castNode(AlterFdwStmt, node));
+ break;
+ case T_AlterForeignServerStmt:
+ deparseAlterForeignServerStmt(str, castNode(AlterForeignServerStmt, node));
+ break;
+ case T_AlterFunctionStmt:
+ deparseAlterFunctionStmt(str, castNode(AlterFunctionStmt, node));
+ break;
+ case T_AlterObjectDependsStmt:
+ deparseAlterObjectDependsStmt(str, castNode(AlterObjectDependsStmt, node));
+ break;
+ case T_AlterObjectSchemaStmt:
+ deparseAlterObjectSchemaStmt(str, castNode(AlterObjectSchemaStmt, node));
+ break;
+ case T_AlterOwnerStmt:
+ deparseAlterOwnerStmt(str, castNode(AlterOwnerStmt, node));
+ break;
+ case T_AlterOperatorStmt:
+ deparseAlterOperatorStmt(str, castNode(AlterOperatorStmt, node));
+ break;
+ case T_AlterPolicyStmt:
+ deparseAlterPolicyStmt(str, castNode(AlterPolicyStmt, node));
+ break;
+ case T_AlterSeqStmt:
+ deparseAlterSeqStmt(str, castNode(AlterSeqStmt, node));
+ break;
+ case T_AlterSystemStmt:
+ deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
+ break;
+ case T_AlterTableStmt:
+ deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
+ break;
+ case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
+ deparseAlterTableSpaceOptionsStmt(str, castNode(AlterTableSpaceOptionsStmt, node));
+ break;
+ case T_AlterPublicationStmt:
+ deparseAlterPublicationStmt(str, castNode(AlterPublicationStmt, node));
+ break;
+ case T_AlterRoleSetStmt:
+ deparseAlterRoleSetStmt(str, castNode(AlterRoleSetStmt, node));
+ break;
+ case T_AlterRoleStmt:
+ deparseAlterRoleStmt(str, castNode(AlterRoleStmt, node));
+ break;
+ case T_AlterSubscriptionStmt:
+ deparseAlterSubscriptionStmt(str, castNode(AlterSubscriptionStmt, node));
+ break;
+ case T_AlterTSConfigurationStmt:
+ deparseAlterTSConfigurationStmt(str, castNode(AlterTSConfigurationStmt, node));
+ break;
+ case T_AlterTSDictionaryStmt:
+ deparseAlterTSDictionaryStmt(str, castNode(AlterTSDictionaryStmt, node));
+ break;
+ case T_AlterUserMappingStmt:
+ deparseAlterUserMappingStmt(str, castNode(AlterUserMappingStmt, node));
+ break;
+ case T_CallStmt:
+ deparseCallStmt(str, castNode(CallStmt, node));
+ break;
+ case T_CheckPointStmt:
+ deparseCheckPointStmt(str, castNode(CheckPointStmt, node));
+ break;
+ case T_ClosePortalStmt:
+ deparseClosePortalStmt(str, castNode(ClosePortalStmt, node));
+ break;
+ case T_ClusterStmt:
+ deparseClusterStmt(str, castNode(ClusterStmt, node));
+ break;
+ case T_CommentStmt:
+ deparseCommentStmt(str, castNode(CommentStmt, node));
+ break;
+ case T_ConstraintsSetStmt:
+ deparseConstraintsSetStmt(str, castNode(ConstraintsSetStmt, node));
+ break;
+ case T_CopyStmt:
+ deparseCopyStmt(str, castNode(CopyStmt, node));
+ break;
+ case T_CreateAmStmt:
+ deparseCreateAmStmt(str, castNode(CreateAmStmt, node));
+ break;
+ case T_CreateTableAsStmt: // "CreateAsStmt" in gram.y
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_CreateCastStmt:
+ deparseCreateCastStmt(str, castNode(CreateCastStmt, node));
+ break;
+ case T_CreateConversionStmt:
+ deparseCreateConversionStmt(str, castNode(CreateConversionStmt, node));
+ break;
+ case T_CreateDomainStmt:
+ deparseCreateDomainStmt(str, castNode(CreateDomainStmt, node));
+ break;
+ case T_CreateExtensionStmt:
+ deparseCreateExtensionStmt(str, castNode(CreateExtensionStmt, node));
+ break;
+ case T_CreateFdwStmt:
+ deparseCreateFdwStmt(str, castNode(CreateFdwStmt, node));
+ break;
+ case T_CreateForeignServerStmt:
+ deparseCreateForeignServerStmt(str, castNode(CreateForeignServerStmt, node));
+ break;
+ case T_CreateForeignTableStmt:
+ deparseCreateForeignTableStmt(str, castNode(CreateForeignTableStmt, node));
+ break;
+ case T_CreateFunctionStmt:
+ deparseCreateFunctionStmt(str, castNode(CreateFunctionStmt, node));
+ break;
+ case T_CreateOpClassStmt:
+ deparseCreateOpClassStmt(str, castNode(CreateOpClassStmt, node));
+ break;
+ case T_CreateOpFamilyStmt:
+ deparseCreateOpFamilyStmt(str, castNode(CreateOpFamilyStmt, node));
+ break;
+ case T_CreatePublicationStmt:
+ deparseCreatePublicationStmt(str, castNode(CreatePublicationStmt, node));
+ break;
+ case T_AlterOpFamilyStmt:
+ deparseAlterOpFamilyStmt(str, castNode(AlterOpFamilyStmt, node));
+ break;
+ case T_CreatePolicyStmt:
+ deparseCreatePolicyStmt(str, castNode(CreatePolicyStmt, node));
+ break;
+ case T_CreatePLangStmt:
+ deparseCreatePLangStmt(str, castNode(CreatePLangStmt, node));
+ break;
+ case T_CreateSchemaStmt:
+ deparseCreateSchemaStmt(str, castNode(CreateSchemaStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_CreateSubscriptionStmt:
+ deparseCreateSubscriptionStmt(str, castNode(CreateSubscriptionStmt, node));
+ break;
+ case T_CreateStatsStmt:
+ deparseCreateStatsStmt(str, castNode(CreateStatsStmt, node));
+ break;
+ case T_CreateTableSpaceStmt:
+ deparseCreateTableSpaceStmt(str, castNode(CreateTableSpaceStmt, node));
+ break;
+ case T_CreateTransformStmt:
+ deparseCreateTransformStmt(str, castNode(CreateTransformStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_CreateEventTrigStmt:
+ deparseCreateEventTrigStmt(str, castNode(CreateEventTrigStmt, node));
+ break;
+ case T_CreateRoleStmt:
+ deparseCreateRoleStmt(str, castNode(CreateRoleStmt, node));
+ break;
+ case T_CreateUserMappingStmt:
+ deparseCreateUserMappingStmt(str, castNode(CreateUserMappingStmt, node));
+ break;
+ case T_CreatedbStmt:
+ deparseCreatedbStmt(str, castNode(CreatedbStmt, node));
+ break;
+ case T_DeallocateStmt:
+ deparseDeallocateStmt(str, castNode(DeallocateStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_DefineStmt:
+ deparseDefineStmt(str, castNode(DefineStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DiscardStmt:
+ deparseDiscardStmt(str, castNode(DiscardStmt, node));
+ break;
+ case T_DoStmt:
+ deparseDoStmt(str, castNode(DoStmt, node));
+ break;
+ case T_DropOwnedStmt:
+ deparseDropOwnedStmt(str, castNode(DropOwnedStmt, node));
+ break;
+ case T_DropStmt:
+ deparseDropStmt(str, castNode(DropStmt, node));
+ break;
+ case T_DropSubscriptionStmt:
+ deparseDropSubscriptionStmt(str, castNode(DropSubscriptionStmt, node));
+ break;
+ case T_DropTableSpaceStmt:
+ deparseDropTableSpaceStmt(str, castNode(DropTableSpaceStmt, node));
+ break;
+ case T_DropRoleStmt:
+ deparseDropRoleStmt(str, castNode(DropRoleStmt, node));
+ break;
+ case T_DropUserMappingStmt:
+ deparseDropUserMappingStmt(str, castNode(DropUserMappingStmt, node));
+ break;
+ case T_DropdbStmt:
+ deparseDropdbStmt(str, castNode(DropdbStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ case T_ExplainStmt:
+ deparseExplainStmt(str, castNode(ExplainStmt, node));
+ break;
+ case T_FetchStmt:
+ deparseFetchStmt(str, castNode(FetchStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_GrantRoleStmt:
+ deparseGrantRoleStmt(str, castNode(GrantRoleStmt, node));
+ break;
+ case T_ImportForeignSchemaStmt:
+ deparseImportForeignSchemaStmt(str, castNode(ImportForeignSchemaStmt, node));
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_ListenStmt:
+ deparseListenStmt(str, castNode(ListenStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_LoadStmt:
+ deparseLoadStmt(str, castNode(LoadStmt, node));
+ break;
+ case T_LockStmt:
+ deparseLockStmt(str, castNode(LockStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ case T_PrepareStmt:
+ deparsePrepareStmt(str, castNode(PrepareStmt, node));
+ break;
+ case T_ReassignOwnedStmt:
+ deparseReassignOwnedStmt(str, castNode(ReassignOwnedStmt, node));
+ break;
+ case T_ReindexStmt:
+ deparseReindexStmt(str, castNode(ReindexStmt, node));
+ break;
+ case T_RenameStmt:
+ deparseRenameStmt(str, castNode(RenameStmt, node));
+ break;
+ case T_RuleStmt:
+ deparseRuleStmt(str, castNode(RuleStmt, node));
+ break;
+ case T_SecLabelStmt:
+ deparseSecLabelStmt(str, castNode(SecLabelStmt, node));
+ break;
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_TransactionStmt:
+ deparseTransactionStmt(str, castNode(TransactionStmt, node));
+ break;
+ case T_TruncateStmt:
+ deparseTruncateStmt(str, castNode(TruncateStmt, node));
+ break;
+ case T_UnlistenStmt:
+ deparseUnlistenStmt(str, castNode(UnlistenStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_VacuumStmt:
+ deparseVacuumStmt(str, castNode(VacuumStmt, node));
+ break;
+ case T_VariableSetStmt:
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, node));
+ break;
+ case T_VariableShowStmt:
+ deparseVariableShowStmt(str, castNode(VariableShowStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ // These node types are created by DefineStmt grammar for CREATE TYPE in some cases
+ case T_CompositeTypeStmt:
+ deparseCompositeTypeStmt(str, castNode(CompositeTypeStmt, node));
+ break;
+ case T_CreateEnumStmt:
+ deparseCreateEnumStmt(str, castNode(CreateEnumStmt, node));
+ break;
+ case T_CreateRangeStmt:
+ deparseCreateRangeStmt(str, castNode(CreateRangeStmt, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
+ }
+}
+#endif
diff --git a/postgres_deparse.12.c b/postgres_deparse.12.c
new file mode 100644
index 0000000..1653b52
--- /dev/null
+++ b/postgres_deparse.12.c
@@ -0,0 +1,9896 @@
+#include "pg_config.h"
+#if(PG_VERSION_NUM >= 120000 && PG_VERSION_NUM < 130000)
+
+// Adapted from https://raw.githubusercontent.com/pganalyze/libpg_query/refs/tags/13-2.2.0/src/pg_query_deparse.c
+
+// Copyright (c) 2015, Lukas Fittl
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "postgres.h"
+#include "catalog/index.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_trigger.h"
+#include "commands/trigger.h"
+#include "common/keywords.h"
+#include "common/kwlookup.h"
+#include "lib/stringinfo.h"
+#include "limits.h"
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "utils/builtins.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/xml.h"
+
+typedef enum DeparseNodeContext {
+ DEPARSE_NODE_CONTEXT_NONE,
+ // Parent node type (and sometimes field)
+ DEPARSE_NODE_CONTEXT_INSERT_RELATION,
+ DEPARSE_NODE_CONTEXT_INSERT_ON_CONFLICT,
+ DEPARSE_NODE_CONTEXT_UPDATE,
+ DEPARSE_NODE_CONTEXT_RETURNING,
+ DEPARSE_NODE_CONTEXT_A_EXPR,
+ DEPARSE_NODE_CONTEXT_XMLATTRIBUTES,
+ DEPARSE_NODE_CONTEXT_XMLNAMESPACES,
+ DEPARSE_NODE_CONTEXT_CREATE_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_TYPE,
+ // Identifier vs constant context
+ DEPARSE_NODE_CONTEXT_IDENTIFIER,
+ DEPARSE_NODE_CONTEXT_CONSTANT
+} DeparseNodeContext;
+
+static void
+removeTrailingSpace(StringInfo str)
+{
+ if (str->len >= 1 && str->data[str->len - 1] == ' ') {
+ str->len -= 1;
+ str->data[str->len] = '\0';
+ }
+}
+
+/*
+ * Append a SQL string literal representing "val" to buf.
+ *
+ * Copied here from postgres_fdw/deparse.c to avoid adding
+ * many additional dependencies.
+ */
+static void
+deparseStringLiteral(StringInfo buf, const char *val)
+{
+ const char *valptr;
+
+ /*
+ * Rather than making assumptions about the remote server's value of
+ * standard_conforming_strings, always use E'foo' syntax if there are any
+ * backslashes. This will fail on remote servers before 8.1, but those
+ * are long out of support.
+ */
+ if (strchr(val, '\\') != NULL)
+ appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
+ appendStringInfoChar(buf, '\'');
+ for (valptr = val; *valptr; valptr++)
+ {
+ char ch = *valptr;
+
+ if (SQL_STR_DOUBLE(ch, true))
+ appendStringInfoChar(buf, ch);
+ appendStringInfoChar(buf, ch);
+ }
+ appendStringInfoChar(buf, '\'');
+}
+
+// Check whether the value is a reserved keyword, to determine escaping for output
+//
+// Note that since the parser lowercases all keywords, this does *not* match when the
+// value is not all-lowercase and a reserved keyword.
+static bool
+isReservedKeyword(const char *val)
+{
+ int kwnum = ScanKeywordLookup(val, &ScanKeywords);
+ bool all_lower_case = true;
+ const char *cp;
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ (*cp >= 'a' && *cp <= 'z') ||
+ (*cp >= '0' && *cp <= '9') ||
+ (*cp == '_')))
+ {
+ all_lower_case = false;
+ break;
+ }
+ }
+
+ return all_lower_case && kwnum >= 0 && ScanKeywordCategories[kwnum] == RESERVED_KEYWORD;
+}
+
+// Returns whether the given value consists only of operator characters
+static bool
+isOp(const char *val)
+{
+ const char *cp;
+
+ Assert(strlen(val) > 0);
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ *cp == '~' ||
+ *cp == '!' ||
+ *cp == '@' ||
+ *cp == '#' ||
+ *cp == '^' ||
+ *cp == '&' ||
+ *cp == '|' ||
+ *cp == '`' ||
+ *cp == '?' ||
+ *cp == '+' ||
+ *cp == '-' ||
+ *cp == '*' ||
+ *cp == '/' ||
+ *cp == '%' ||
+ *cp == '<' ||
+ *cp == '>' ||
+ *cp == '='))
+ return false;
+ }
+
+ return true;
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt);
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause);
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context);
+static void deparseResTarget(StringInfo str, ResTarget *res_target, DeparseNodeContext context);
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt);
+static void deparseAlias(StringInfo str, Alias *alias);
+static void deparseWindowDef(StringInfo str, WindowDef* window_def);
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref);
+static void deparseSubLink(StringInfo str, SubLink* sub_link);
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context);
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr);
+static void deparseAStar(StringInfo str, A_Star* a_star);
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause);
+static void deparseSortBy(StringInfo str, SortBy* sort_by);
+static void deparseParamRef(StringInfo str, ParamRef* param_ref);
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function);
+static void deparseWithClause(StringInfo str, WithClause *with_clause);
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr);
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte);
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect);
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func);
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr * array_expr);
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr);
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast);
+static void deparseTypeName(StringInfo str, TypeName *type_name);
+static void deparseNullTest(StringInfo str, NullTest *null_test);
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr);
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when);
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection);
+static void deparseAIndices(StringInfo str, A_Indices *a_indices);
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr);
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test);
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def);
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt);
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause);
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem);
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt);
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt);
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause);
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default);
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt);
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt);
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter);
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec);
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt);
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt);
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt);
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample);
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func);
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set);
+static void deparseFuncCall(StringInfo str, FuncCall *func_call);
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr);
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr);
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize);
+static void deparseConstraint(StringInfo str, Constraint *constraint);
+static void deparseSchemaStmt(StringInfo str, Node *node);
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt);
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition);
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item);
+static void deparseAConst(StringInfo str, A_Const *a_const);
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr);
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func);
+
+static void deparsePreparableStmt(StringInfo str, Node *node);
+static void deparseRuleActionStmt(StringInfo str, Node *node);
+static void deparseExplainableStmt(StringInfo str, Node *node);
+static void deparseStmt(StringInfo str, Node *node);
+static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context);
+
+// "any_name" in gram.y
+static void deparseAnyName(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, parts)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipFirst(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+ int idx = 0;
+
+ foreach(lc, parts)
+ {
+ if(idx < 1) {
+ idx++;
+ continue;
+ }
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipLast(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+ int idx = 0;
+
+ foreach (lc, parts)
+ {
+ if (lnext(lc))
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (idx < list_length(parts) - 2)
+ appendStringInfoChar(str, '.');
+ }
+ idx++;
+ }
+}
+
+// "a_expr" / "b_expr" in gram.y
+static void deparseExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Expr:
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_NullTest:
+ deparseNullTest(str, castNode(NullTest, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_BoolExpr:
+ deparseBoolExpr(str, castNode(BoolExpr, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_SetToDefault:
+ deparseSetToDefault(str, castNode(SetToDefault, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CollateClause:
+ deparseCollateClause(str, castNode(CollateClause, node));
+ break;
+ case T_CurrentOfExpr:
+ deparseCurrentOfExpr(str, castNode(CurrentOfExpr, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_BooleanTest:
+ deparseBooleanTest(str, castNode(BooleanTest, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "c_expr" in gram.y
+static void deparseCExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_A_Expr:
+ appendStringInfoChar(str, '(');
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ')');
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in c_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "expr_list" in gram.y
+static void deparseExprList(StringInfo str, List *exprs)
+{
+ ListCell *lc;
+
+ foreach(lc, exprs)
+ {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
+static void deparseColId(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "ColLabel", "attr_name"
+//
+// Note this is kept separate from ColId in case we ever want to be more
+// specific on how to handle keywords here
+static void deparseColLabel(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "SignedIconst" and "Iconst" in gram.y
+static void deparseSignedIconst(StringInfo str, Node *node)
+{
+ appendStringInfo(str, "%d", intVal(node));
+}
+
+// "indirection" and "opt_indirection" in gram.y
+static void deparseOptIndirection(StringInfo str, List *indirection, int N)
+{
+ ListCell *lc = NULL;
+ int idx = 0;
+
+ foreach(lc, indirection)
+ {
+ if(idx < N) {
+ idx++;
+ continue;
+ }
+ if (IsA(lfirst(lc), String))
+ {
+ appendStringInfoChar(str, '.');
+ deparseColLabel(str, strVal(lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Star))
+ {
+ appendStringInfoString(str, ".*");
+ }
+ else if (IsA(lfirst(lc), A_Indices))
+ {
+ deparseAIndices(str, castNode(A_Indices, lfirst(lc)));
+ }
+ else
+ {
+ // No other nodes should appear here
+ Assert(false);
+ }
+ }
+}
+
+// "role_list" in gram.y
+static void deparseRoleList(StringInfo str, List *roles)
+{
+ ListCell *lc;
+
+ foreach(lc, roles)
+ {
+ RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
+ deparseRoleSpec(str, role_spec);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SimpleTypename" in gram.y
+static void deparseSimpleTypename(StringInfo str, Node *node)
+{
+ deparseTypeName(str, castNode(TypeName, node));
+}
+
+// "NumericOnly" in gram.y
+static void deparseNumericOnly(StringInfo str, Value *value)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ appendStringInfo(str, "%d", value->val.ival);
+ break;
+ case T_Float:
+ appendStringInfoString(str, value->val.str);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "NumericOnly_list" in gram.y
+static void deparseNumericOnlyList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseNumericOnly(str, (Value *) lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SeqOptElem" in gram.y
+static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseSimpleTypename(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cache") == 0)
+ {
+ appendStringInfoString(str, "CACHE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NO CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "increment") == 0)
+ {
+ appendStringInfoString(str, "INCREMENT ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MAXVALUE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MAXVALUE");
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MINVALUE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MINVALUE");
+ }
+ else if (strcmp(def_elem->defname, "owned_by") == 0)
+ {
+ appendStringInfoString(str, "OWNED BY ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "sequence_name") == 0)
+ {
+ appendStringInfoString(str, "SEQUENCE NAME ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "start") == 0)
+ {
+ appendStringInfoString(str, "START ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "SeqOptList" in gram.y
+static void deparseSeqOptList(StringInfo str, List *options)
+{
+ ListCell *lc;
+ Assert(list_length(options) > 0);
+ foreach (lc, options)
+ {
+ deparseSeqOptElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "OptSeqOptList" in gram.y
+static void deparseOptSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ deparseSeqOptList(str, options);
+}
+
+// "OptParenthesizedSeqOptList" in gram.y
+static void deparseOptParenthesizedSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseSeqOptList(str, options);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "opt_drop_behavior" in gram.y
+static void deparseOptDropBehavior(StringInfo str, DropBehavior behavior)
+{
+ switch (behavior)
+ {
+ case DROP_RESTRICT:
+ // Default
+ break;
+ case DROP_CASCADE:
+ appendStringInfoString(str, "CASCADE ");
+ break;
+ }
+}
+
+// "any_operator" in gram.y
+static void deparseAnyOperator(StringInfo str, List *op)
+{
+ Assert(isOp(strVal(llast(op))));
+ if (list_length(op) == 2)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(linitial(op))));
+ appendStringInfoChar(str, '.');
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else if (list_length(op) == 1)
+ {
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "qual_Op" and "qual_all_Op" in gram.y
+static void deparseQualOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// "subquery_Op" in gram.y
+static void deparseSubqueryOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
+ {
+ appendStringInfoString(str, "LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
+ {
+ appendStringInfoString(str, "NOT LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
+ {
+ appendStringInfoString(str, "ILIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
+ {
+ appendStringInfoString(str, "NOT ILIKE");
+ }
+ else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// Not present directly in gram.y (usually matched by ColLabel)
+static void deparseGenericDefElemName(StringInfo str, const char *in)
+{
+ Assert(in != NULL);
+ char *val = pstrdup(in);
+ for (unsigned char *p = (unsigned char *) val; *p; p++)
+ *p = pg_toupper(*p);
+ appendStringInfoString(str, val);
+ pfree(val);
+}
+
+// "def_arg" and "operator_def_arg" in gram.y
+static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
+{
+ if (IsA(arg, TypeName)) // func_type
+ {
+ deparseTypeName(str, castNode(TypeName, arg));
+ }
+ else if (IsA(arg, List)) // qual_all_Op
+ {
+ List *l = castNode(List, arg);
+ Assert(list_length(l) == 1 || list_length(l) == 2);
+
+ // Schema qualified operator
+ if (list_length(l) == 2)
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, l);
+ appendStringInfoChar(str, ')');
+ }
+ else if (list_length(l) == 1)
+ {
+ appendStringInfoString(str, strVal(linitial(l)));
+ }
+ }
+ else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
+ {
+ deparseValue(str, (Value *) arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (IsA(arg, String))
+ {
+ char *s = strVal(arg);
+ if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) // NONE
+ {
+ appendStringInfoString(str, "NONE");
+ }
+ else if (isReservedKeyword(s)) // reserved_keyword
+ {
+ appendStringInfoString(str, s);
+ }
+ else // Sconst
+ {
+ deparseStringLiteral(str, s);
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "definition" in gram.y
+static void deparseDefinition(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL) {
+ appendStringInfoString(str, " = ");
+ deparseDefArg(str, def_elem->arg, false);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "opt_definition" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptDefinition(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseDefinition(str, options);
+ }
+}
+
+// "create_generic_options" in gram.y
+static void deparseCreateGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ if (options == NULL)
+ return;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "common_func_opt_item" in gram.y
+static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "CALLED ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
+ {
+ appendStringInfoString(str, "IMMUTABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
+ {
+ appendStringInfoString(str, "STABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
+ {
+ appendStringInfoString(str, "VOLATILE");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "SECURITY DEFINER");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "SECURITY INVOKER");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOT LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "cost") == 0)
+ {
+ appendStringInfoString(str, "COST ");
+ deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "rows") == 0)
+ {
+ appendStringInfoString(str, "ROWS ");
+ deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "support") == 0)
+ {
+ appendStringInfoString(str, "SUPPORT ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
+ {
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "parallel") == 0)
+ {
+ appendStringInfoString(str, "PARALLEL ");
+ appendStringInfoString(str, quote_identifier(strVal(def_elem->arg)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "NonReservedWord_or_Sconst" in gram.y
+//
+// Note since both identifiers and string constants are allowed here, we
+// currently always return an identifier, except:
+//
+// 1) when the string is empty (since an empty identifier can't be scanned)
+// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
+static void deparseNonReservedWordOrSconst(StringInfo str, const char *val)
+{
+ if (strlen(val) == 0)
+ appendStringInfoString(str, "''");
+ else if (strlen(val) >= NAMEDATALEN)
+ deparseStringLiteral(str, val);
+ else
+ appendStringInfoString(str, quote_identifier(val));
+}
+
+// "func_as" in gram.y
+static void deparseFuncAs(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ char *strval = strVal(lfirst(lc));
+ if (strstr(strval, "$$") == NULL)
+ {
+ appendStringInfoString(str, "$$");
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, "$$");
+ }
+ else
+ {
+ deparseStringLiteral(str, strval);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createfunc_opt_item" in gram.y
+static void deparseCreateFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc = NULL;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseFuncAs(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "transform") == 0)
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, "TRANSFORM ");
+ foreach (lc, l)
+ {
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ else if (strcmp(def_elem->defname, "window") == 0)
+ {
+ appendStringInfoString(str, "WINDOW");
+ }
+ else
+ {
+ deparseCommonFuncOptItem(str, def_elem);
+ }
+}
+
+// "alter_generic_options" in gram.y
+static void deparseAlterGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ switch (def_elem->defaction)
+ {
+ case DEFELEM_UNSPEC:
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ break;
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "func_name" in gram.y
+static void deparseFuncName(StringInfo str, List *func_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, func_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "function_with_argtypes" in gram.y
+static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ if (!object_with_args->args_unspecified)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, object_with_args->objargs)
+ {
+ if (IsA(lfirst(lc), TypeName))
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ else
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "function_with_argtypes_list" in gram.y
+static void deparseFunctionWithArgtypesList(StringInfo str, List *l)
+{
+ ListCell *lc;
+
+ foreach(lc, l)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "operator_with_argtypes" in gram.y
+static void deparseOperatorWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ deparseAnyOperator(str, object_with_args->objname);
+
+ Assert(list_length(object_with_args->objargs) == 2);
+ appendStringInfoChar(str, '(');
+ if (linitial(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, linitial(object_with_args->objargs)));
+ appendStringInfoString(str, ", ");
+ if (lsecond(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, lsecond(object_with_args->objargs)));
+ appendStringInfoChar(str, ')');
+}
+
+// "aggr_args" in gram.y
+static void deparseAggrArgs(StringInfo str, List *aggr_args)
+{
+ Assert(list_length(aggr_args) == 2);
+
+ ListCell *lc = NULL;
+ List *args = linitial(aggr_args);
+ int order_by_pos = intVal(lsecond(aggr_args));
+ int idx = 0;
+
+ appendStringInfoChar(str, '(');
+ if (args == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, args)
+ {
+ if (idx == order_by_pos)
+ {
+ if (idx > 0)
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, "ORDER BY ");
+ }
+ else if (idx > 0)
+ {
+ appendStringInfoString(str, ", ");
+ }
+
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ idx++;
+ }
+
+ // Repeat the last direct arg as a ordered arg to handle the
+ // simplification done by makeOrderedSetArgs in gram.y
+ if (order_by_pos == list_length(args))
+ {
+ appendStringInfoString(str, " ORDER BY ");
+ deparseFunctionParameter(str, castNode(FunctionParameter, llast(args)));
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "aggregate_with_argtypes" in gram.y
+static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc = NULL;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ appendStringInfoChar(str, '(');
+ if (object_with_args->objargs == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, object_with_args->objargs)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "columnList" in gram.y
+static void deparseColumnList(StringInfo str, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptTemp" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptTemp(StringInfo str, char relpersistence)
+{
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_PERMANENT:
+ // Default
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ appendStringInfoString(str, "UNLOGGED ");
+ break;
+ case RELPERSISTENCE_TEMP:
+ appendStringInfoString(str, "TEMPORARY ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+// "relation_expr_list" in gram.y
+static void deparseRelationExprList(StringInfo str, List *relation_exprs)
+{
+ ListCell *lc = NULL;
+ foreach(lc, relation_exprs)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "handler_name" in gram.y
+static void deparseHandlerName(StringInfo str, List *handler_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, handler_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "fdw_options" in gram.y
+static void deparseFdwOptions(StringInfo str, List *fdw_options)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, fdw_options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO HANDLER ");
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO VALIDATOR ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "type_list" in gram.y
+static void deparseTypeList(StringInfo str, List *type_list)
+{
+ ListCell *lc = NULL;
+ foreach(lc, type_list)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_boolean_or_string" in gram.y
+static void deparseOptBooleanOrString(StringInfo str, char *s)
+{
+ if (s == NULL)
+ return; // No value set
+ else if (strcmp(s, "true") == 0)
+ appendStringInfoString(str, "TRUE");
+ else if (strcmp(s, "false") == 0)
+ appendStringInfoString(str, "FALSE");
+ else if (strcmp(s, "on") == 0)
+ appendStringInfoString(str, "ON");
+ else if (strcmp(s, "off") == 0)
+ appendStringInfoString(str, "OFF");
+ else
+ deparseNonReservedWordOrSconst(str, s);
+}
+
+// "var_name"
+//
+// Note this is kept separate from ColId in case we want to improve the
+// output of namespaced variable names
+static void deparseVarName(StringInfo str, char *s)
+{
+ deparseColId(str, s);
+}
+
+// "var_list"
+static void deparseVarList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, lfirst(lc));
+ if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
+ deparseNumericOnly(str, (Value *) &a_const->val);
+ else if (IsA(&a_const->val, String))
+ deparseOptBooleanOrString(str, strVal(&a_const->val));
+ else
+ Assert(false);
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "transaction_mode_list" in gram.y
+static void deparseTransactionModeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "transaction_isolation") == 0)
+ {
+ char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
+ appendStringInfoString(str, "ISOLATION LEVEL ");
+ if (strcmp(s, "read uncommitted") == 0)
+ appendStringInfoString(str, "READ UNCOMMITTED");
+ else if (strcmp(s, "read committed") == 0)
+ appendStringInfoString(str, "READ COMMITTED");
+ else if (strcmp(s, "repeatable read") == 0)
+ appendStringInfoString(str, "REPEATABLE READ");
+ else if (strcmp(s, "serializable") == 0)
+ appendStringInfoString(str, "SERIALIZABLE");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "READ ONLY");
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "READ WRITE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "DEFERRABLE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "NOT DEFERRABLE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "alter_identity_column_option_list" in gram.y
+static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "generated") == 0)
+ {
+ appendStringInfoString(str, "SET GENERATED ");
+ if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
+ appendStringInfoString(str, "ALWAYS");
+ else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+ appendStringInfoString(str, "BY DEFAULT");
+ else
+ Assert(false);
+ }
+ else
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSeqOptElem(str, def_elem);
+ }
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "reloptions" in gram.y
+static void deparseRelOptions(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (def_elem->defnamespace != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defnamespace));
+ appendStringInfoChar(str, '.');
+ }
+ if (def_elem->defname != NULL)
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->defname != NULL && def_elem->arg != NULL)
+ appendStringInfoChar(str, '=');
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, false);
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "OptWith" and "opt_reloptions" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptWith(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseRelOptions(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "target_list" and "opt_target_list" in gram.y
+static void deparseTargetList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+
+ if (res_target->val == NULL)
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
+ else if (IsA(res_target->val, ColumnRef))
+ deparseColumnRef(str, castNode(ColumnRef, res_target->val));
+ else
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL) {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "insert_column_list" in gram.y
+static void deparseInsertColumnList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->name != NULL);
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ deparseOptIndirection(str, res_target->indirection, 0);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_attribute_list" in gram.y
+static void deparseXmlAttributeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_namespace_list" in gram.y
+static void deparseXmlNamespaceList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (res_target->name == NULL)
+ appendStringInfoString(str, "DEFAULT ");
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "table_ref" in gram.y
+static void deparseTableRef(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_RangeVar:
+ deparseRangeVar(str, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_RangeTableSample:
+ deparseRangeTableSample(str, castNode(RangeTableSample, node));
+ break;
+ case T_RangeFunction:
+ deparseRangeFunction(str, castNode(RangeFunction, node));
+ break;
+ case T_RangeTableFunc:
+ deparseRangeTableFunc(str, castNode(RangeTableFunc, node));
+ break;
+ case T_RangeSubselect:
+ deparseRangeSubselect(str, castNode(RangeSubselect, node));
+ break;
+ case T_JoinExpr:
+ deparseJoinExpr(str, castNode(JoinExpr, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "from_list" in gram.y
+static void deparseFromList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseTableRef(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "from_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseFromClause(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseFromList(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "where_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereClause(StringInfo str, Node *node)
+{
+ if (node != NULL)
+ {
+ appendStringInfoString(str, "WHERE ");
+ deparseExpr(str, node);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "group_by_list" in gram.y
+static void deparseGroupByList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), GroupingSet))
+ deparseGroupingSet(str, castNode(GroupingSet, lfirst(lc)));
+ else
+ deparseExpr(str, lfirst(lc));
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "set_target" in gram.y
+static void deparseSetTarget(StringInfo str, ResTarget *res_target)
+{
+ Assert(res_target->name != NULL);
+ deparseColId(str, res_target->name);
+ deparseOptIndirection(str, res_target->indirection, 0);
+}
+
+// "any_name_list" in gram.y
+static void deparseAnyNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseAnyName(str, castNode(List, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "name_list" in gram.y
+static void deparseNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseColId(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_sort_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptSortClause(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "ORDER BY ");
+
+ foreach(lc, l)
+ {
+ deparseSortBy(str, castNode(SortBy, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "func_arg_expr" in gram.y
+static void deparseFuncArgExpr(StringInfo str, Node *node)
+{
+ if (IsA(node, NamedArgExpr))
+ {
+ NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
+ appendStringInfoString(str, named_arg_expr->name);
+ appendStringInfoString(str, " := ");
+ deparseExpr(str, (Node *) named_arg_expr->arg);
+ }
+ else
+ {
+ deparseExpr(str, node);
+ }
+}
+
+// "set_clause_list" in gram.y
+static void deparseSetClauseList(StringInfo str, List *target_list)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ int skip_next_n_elems = 0;
+ int idx = 0;
+ int idx2 = 0;
+
+ Assert(list_length(target_list) > 0);
+
+ foreach(lc, target_list)
+ {
+ if (skip_next_n_elems > 0)
+ {
+ skip_next_n_elems--;
+ continue;
+ }
+
+ if (idx != 0)
+ appendStringInfoString(str, ", ");
+
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (IsA(res_target->val, MultiAssignRef))
+ {
+ MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
+ appendStringInfoString(str, "(");
+ idx2 = 0;
+ for_each_cell(lc2, lc)
+ {
+ deparseSetTarget(str, castNode(ResTarget, lfirst(lc2)));
+ if (idx2 == r->ncolumns - 1) // Last element in this multi-assign
+ break;
+ else if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ idx2++;
+ }
+ appendStringInfoString(str, ") = ");
+ deparseExpr(str, r->source);
+ skip_next_n_elems = r->ncolumns - 1;
+ }
+ else
+ {
+ deparseSetTarget(str, res_target);
+ appendStringInfoString(str, " = ");
+ deparseExpr(str, res_target->val);
+ }
+ idx++;
+ }
+}
+
+// "func_expr_windowless" in gram.y
+static void deparseFuncExprWindowless(StringInfo str, Node* node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "opt_collate" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptCollate(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "index_elem" in gram.y
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem)
+{
+ if (index_elem->name != NULL)
+ {
+ deparseColId(str, index_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (index_elem->expr != NULL)
+ {
+ switch (nodeTag(index_elem->expr))
+ {
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_TypeCast:
+ case T_CoalesceExpr:
+ case T_MinMaxExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ deparseFuncExprWindowless(str, index_elem->expr);
+ break;
+ default:
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, index_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseOptCollate(str, index_elem->collation);
+
+ if (list_length(index_elem->opclass) > 0)
+ {
+ deparseAnyName(str, index_elem->opclass);
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (index_elem->ordering)
+ {
+ case SORTBY_DEFAULT:
+ // Default
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ // Not allowed in CREATE INDEX
+ Assert(false);
+ break;
+ }
+
+ switch (index_elem->nulls_ordering)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ // Default
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+// "qualified_name_list" in gram.y
+static void deparseQualifiedNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptInherit" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptInherit(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "INHERITS (");
+ deparseQualifiedNameList(str, l);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+// "privilege_target" in gram.y
+static void deparsePrivilegeTarget(StringInfo str, GrantTargetType targtype, ObjectType objtype, List *objs)
+{
+ switch (targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "FOREIGN SERVER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyNameList(str, objs);
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnlyList(str, objs);
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "ALL TABLES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "ALL SEQUENCES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "ALL FUNCTIONS IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "ALL PROCEDURES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ALL ROUTINES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_DEFAULTS: // defacl_privilege_target
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLES");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTIONS");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPES");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMAS");
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ }
+}
+
+// "opclass_item_list" in gram.y
+static void deparseOpclassItemList(StringInfo str, List *items)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, items)
+ {
+ deparseCreateOpClassItem(str, castNode(CreateOpClassItem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createdb_opt_list" in gram.y
+static void deparseCreatedbOptList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "connection_limit") == 0)
+ appendStringInfoString(str, "CONNECTION LIMIT");
+ else
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ appendStringInfoString(str, "DEFAULT");
+ else if (IsA(def_elem->arg, Integer))
+ deparseSignedIconst(str, def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
+{
+ const ListCell *lc = NULL;
+ const ListCell *lc2 = NULL;
+
+ if (stmt->withClause)
+ {
+ deparseWithClause(str, stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (stmt->op) {
+ case SETOP_NONE:
+ if (list_length(stmt->valuesLists) > 0)
+ {
+ const ListCell *lc;
+ appendStringInfoString(str, "VALUES ");
+
+ foreach(lc, stmt->valuesLists)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, lfirst(lc));
+ appendStringInfoChar(str, ')');
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ }
+
+ appendStringInfoString(str, "SELECT ");
+
+ if (list_length(stmt->targetList) > 0)
+ {
+ if (stmt->distinctClause != NULL)
+ {
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
+ {
+ appendStringInfoString(str, "ON (");
+ deparseExprList(str, stmt->distinctClause);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ deparseTargetList(str, stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->intoClause != NULL)
+ {
+ appendStringInfoString(str, "INTO ");
+ deparseOptTemp(str, stmt->intoClause->rel->relpersistence);
+ deparseIntoClause(str, stmt->intoClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, stmt->fromClause);
+ deparseWhereClause(str, stmt->whereClause);
+
+ if (list_length(stmt->groupClause) > 0)
+ {
+ appendStringInfoString(str, "GROUP BY ");
+ deparseGroupByList(str, stmt->groupClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->havingClause != NULL)
+ {
+ appendStringInfoString(str, "HAVING ");
+ deparseExpr(str, stmt->havingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->windowClause != NULL)
+ {
+ appendStringInfoString(str, "WINDOW ");
+ foreach(lc, stmt->windowClause)
+ {
+ WindowDef *window_def = castNode(WindowDef, lfirst(lc));
+ Assert(window_def->name != NULL);
+ appendStringInfoString(str, window_def->name);
+ appendStringInfoString(str, " AS ");
+ deparseWindowDef(str, window_def);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case SETOP_UNION:
+ case SETOP_INTERSECT:
+ case SETOP_EXCEPT:
+ {
+ bool need_larg_parens =
+ list_length(stmt->larg->sortClause) > 0 ||
+ stmt->larg->limitOffset != NULL ||
+ stmt->larg->limitCount != NULL ||
+ list_length(stmt->larg->lockingClause) > 0 ||
+ stmt->larg->withClause != NULL ||
+ stmt->larg->op != SETOP_NONE;
+ bool need_rarg_parens =
+ list_length(stmt->rarg->sortClause) > 0 ||
+ stmt->rarg->limitOffset != NULL ||
+ stmt->rarg->limitCount != NULL ||
+ list_length(stmt->rarg->lockingClause) > 0 ||
+ stmt->rarg->withClause != NULL ||
+ stmt->rarg->op != SETOP_NONE;
+ if (need_larg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->larg);
+ if (need_larg_parens)
+ appendStringInfoChar(str, ')');
+ switch (stmt->op)
+ {
+ case SETOP_UNION:
+ appendStringInfoString(str, " UNION ");
+ break;
+ case SETOP_INTERSECT:
+ appendStringInfoString(str, " INTERSECT ");
+ break;
+ case SETOP_EXCEPT:
+ appendStringInfoString(str, " EXCEPT ");
+ break;
+ default:
+ Assert(false);
+ }
+ if (stmt->all)
+ appendStringInfoString(str, "ALL ");
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ }
+
+ deparseOptSortClause(str, stmt->sortClause);
+
+ if (stmt->limitCount != NULL)
+ {
+ if (IsA(stmt->limitCount, A_Const) && IsA(&castNode(A_Const, stmt->limitCount)->val, Null))
+ appendStringInfoString(str, "ALL");
+ else
+ deparseCExpr(str, stmt->limitCount);
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->limitOffset != NULL)
+ {
+ appendStringInfoString(str, "OFFSET ");
+ deparseExpr(str, stmt->limitOffset);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(stmt->lockingClause) > 0)
+ {
+ foreach(lc, stmt->lockingClause)
+ {
+ deparseLockingClause(str, castNode(LockingClause, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, " ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause)
+{
+ ListCell *lc;
+
+ deparseRangeVar(str, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE); /* target relation name */
+
+ if (list_length(into_clause->colNames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, into_clause->colNames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (into_clause->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(into_clause->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptWith(str, into_clause->options);
+
+ switch (into_clause->onCommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (into_clause->tableSpaceName != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(into_clause->tableSpaceName));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context)
+{
+ if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ONLY ");
+
+ if (range_var->catalogname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->catalogname));
+ appendStringInfoChar(str, '.');
+ }
+
+ if (range_var->schemaname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->schemaname));
+ appendStringInfoChar(str, '.');
+ }
+
+ Assert(range_var->relname != NULL);
+ appendStringInfoString(str, quote_identifier(range_var->relname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_var->alias != NULL)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_var->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt)
+{
+ if (raw_stmt->stmt == NULL)
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
+
+ deparseStmt(str, raw_stmt->stmt);
+}
+
+static void deparseAlias(StringInfo str, Alias *alias)
+{
+ appendStringInfoString(str, quote_identifier(alias->aliasname));
+
+ if (list_length(alias->colnames) > 0)
+ {
+ const ListCell *lc = NULL;
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, alias->colnames);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseAConst(StringInfo str, A_Const *a_const)
+{
+ deparseValue(str, &a_const->val, DEPARSE_NODE_CONTEXT_CONSTANT);
+}
+
+static void deparseFuncCall(StringInfo str, FuncCall *func_call)
+{
+ const ListCell *lc = NULL;
+
+ Assert(list_length(func_call->funcname) > 0);
+
+ if (list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "OVERLAY(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PLACING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ deparseFuncName(str, func_call->funcname);
+ appendStringInfoChar(str, '(');
+
+ if (func_call->agg_distinct)
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (func_call->agg_star)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (list_length(func_call->args) > 0)
+ {
+ foreach(lc, func_call->args)
+ {
+ if (func_call->func_variadic && !lnext(lc))
+ appendStringInfoString(str, "VARIADIC ");
+ deparseFuncArgExpr(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (func_call->agg_order != NULL && !func_call->agg_within_group)
+ {
+ deparseOptSortClause(str, func_call->agg_order);
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+
+ if (func_call->agg_order != NULL && func_call->agg_within_group)
+ {
+ appendStringInfoString(str, "WITHIN GROUP (");
+ deparseOptSortClause(str, func_call->agg_order);
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->agg_filter)
+ {
+ appendStringInfoString(str, "FILTER (WHERE ");
+ deparseExpr(str, func_call->agg_filter);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->over)
+ {
+ appendStringInfoString(str, "OVER ");
+ if (func_call->over->name)
+ appendStringInfoString(str, func_call->over->name);
+ else
+ deparseWindowDef(str, func_call->over);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseWindowDef(StringInfo str, WindowDef* window_def)
+{
+ ListCell *lc;
+
+ // The parent node is responsible for outputting window_def->name
+
+ appendStringInfoChar(str, '(');
+
+ if (window_def->refname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(window_def->refname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(window_def->partitionClause) > 0)
+ {
+ appendStringInfoString(str, "PARTITION BY ");
+ deparseExprList(str, window_def->partitionClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptSortClause(str, window_def->orderClause);
+
+ if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
+ {
+ if (window_def->frameOptions & FRAMEOPTION_RANGE)
+ appendStringInfoString(str, "RANGE ");
+ else if (window_def->frameOptions & FRAMEOPTION_ROWS)
+ appendStringInfoString(str, "ROWS ");
+ else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
+ appendStringInfoString(str, "GROUPS ");
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ appendStringInfoString(str, "BETWEEN ");
+
+ // frame_start
+ if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ {
+ appendStringInfoString(str, "UNBOUNDED PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ {
+ appendStringInfoString(str, "AND ");
+
+ // frame_end
+ if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
+ {
+ appendStringInfoString(str, "UNBOUNDED FOLLOWING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
+ appendStringInfoString(str, "EXCLUDE CURRENT ROW ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
+ appendStringInfoString(str, "EXCLUDE GROUP ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
+ appendStringInfoString(str, "EXCLUDE TIES ");
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref)
+{
+ Assert(list_length(column_ref->fields) >= 1);
+
+ if (IsA(linitial(column_ref->fields), A_Star))
+ deparseAStar(str, castNode(A_Star, linitial(column_ref->fields)));
+ else if (IsA(linitial(column_ref->fields), String))
+ deparseColLabel(str, strVal(linitial(column_ref->fields)));
+
+ deparseOptIndirection(str, column_ref->fields, 1);
+}
+
+static void deparseSubLink(StringInfo str, SubLink* sub_link)
+{
+ switch (sub_link->subLinkType) {
+ case EXISTS_SUBLINK:
+ appendStringInfoString(str, "EXISTS (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ALL_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ALL (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ANY_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ if (list_length(sub_link->operName) > 0)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ANY ");
+ }
+ else
+ {
+ appendStringInfoString(str, " IN ");
+ }
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ROWCOMPARE_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case EXPR_SUBLINK:
+ appendStringInfoString(str, "(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case MULTIEXPR_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case ARRAY_SUBLINK:
+ appendStringInfoString(str, "ARRAY(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case CTE_SUBLINK: /* for SubPlans only */
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context)
+{
+ ListCell *lc;
+ char *name;
+
+ bool need_lexpr_parens = a_expr->lexpr != NULL && (IsA(a_expr->lexpr, BoolExpr) || IsA(a_expr->lexpr, NullTest) || IsA(a_expr->lexpr, A_Expr));
+ bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
+
+ switch (a_expr->kind) {
+ case AEXPR_OP: /* normal operator */
+ {
+ bool need_outer_parens = context == DEPARSE_NODE_CONTEXT_A_EXPR;
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, '(');
+ if (a_expr->lexpr != NULL)
+ {
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ deparseQualOp(str, a_expr->name);
+ if (a_expr->rexpr != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ }
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, ')');
+ }
+ return;
+ case AEXPR_OP_ANY: /* scalar op ANY (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ANY(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OP_ALL: /* scalar op ALL (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ALL(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoString(str, " IS DISTINCT FROM ");
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, " IS NOT DISTINCT FROM ");
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_NULLIF: /* NULLIF - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ appendStringInfoString(str, "NULLIF(");
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OF: /* IS [NOT] OF - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IS OF ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "IS NOT OF ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IN ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "NOT IN ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ if (IsA(a_expr->rexpr, SubLink))
+ deparseSubLink(str, castNode(SubLink, a_expr->rexpr));
+ else
+ deparseExprList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~~") == 0) {
+ appendStringInfoString(str, "LIKE ");
+ } else if (strcmp(name, "!~~") == 0) {
+ appendStringInfoString(str, "NOT LIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~~*") == 0) {
+ appendStringInfoString(str, "ILIKE ");
+ } else if (strcmp(name, "!~~*") == 0) {
+ appendStringInfoString(str, "NOT ILIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~") == 0) {
+ appendStringInfoString(str, "SIMILAR TO ");
+ } else if (strcmp(name, "!~") == 0) {
+ appendStringInfoString(str, "NOT SIMILAR TO ");
+ } else {
+ Assert(false);
+ }
+
+ FuncCall *n = castNode(FuncCall, a_expr->rexpr);
+ Assert(list_length(n->funcname) == 2);
+ Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
+ Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
+ Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
+
+ deparseExpr(str, linitial(n->args));
+ if (list_length(n->args) == 2)
+ {
+ appendStringInfoString(str, " ESCAPE ");
+ deparseExpr(str, lsecond(n->args));
+ }
+
+ return;
+ case AEXPR_BETWEEN: /* name must be "BETWEEN" */
+ case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
+ case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
+ case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, strVal(linitial(a_expr->name)));
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, castNode(List, a_expr->rexpr)) {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case AEXPR_PAREN: /* nameless dummy node for parentheses */
+ // Not present in parse trees when operator_precedence_warning is turned off
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr)
+{
+ const ListCell *lc = NULL;
+ switch (bool_expr->boolop)
+ {
+ case AND_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case OR_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(lc))
+ appendStringInfoString(str, " OR ");
+ }
+ return;
+ case NOT_EXPR:
+ Assert(list_length(bool_expr->args) == 1);
+ bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
+ appendStringInfoString(str, "NOT ");
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(bool_expr->args));
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ }
+}
+
+static void deparseAStar(StringInfo str, A_Star *a_star)
+{
+ appendStringInfoChar(str, '*');
+}
+
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause)
+{
+ ListCell *lc;
+ if (collate_clause->arg != NULL)
+ {
+ bool need_parens = IsA(collate_clause->arg, A_Expr);
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, collate_clause->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, collate_clause->collname);
+}
+
+static void deparseSortBy(StringInfo str, SortBy* sort_by)
+{
+ deparseExpr(str, sort_by->node);
+ appendStringInfoChar(str, ' ');
+
+ switch (sort_by->sortby_dir)
+ {
+ case SORTBY_DEFAULT:
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ appendStringInfoString(str, "USING ");
+ deparseQualOp(str, sort_by->useOp);
+ break;
+ }
+
+ switch (sort_by->sortby_nulls)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseParamRef(StringInfo str, ParamRef* param_ref)
+{
+ if (param_ref->number == 0) {
+ appendStringInfoChar(str, '?');
+ } else {
+ appendStringInfo(str, "$%d", param_ref->number);
+ }
+}
+
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function)
+{
+ switch (sql_value_function->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ appendStringInfoString(str, "current_date");
+ break;
+ case SVFOP_CURRENT_TIME:
+ appendStringInfoString(str, "current_time");
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ appendStringInfoString(str, "current_time"); // with precision
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ appendStringInfoString(str, "current_timestamp");
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ appendStringInfoString(str, "current_timestamp"); // with precision
+ break;
+ case SVFOP_LOCALTIME:
+ appendStringInfoString(str, "localtime");
+ break;
+ case SVFOP_LOCALTIME_N:
+ appendStringInfoString(str, "localtime"); // with precision
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ appendStringInfoString(str, "localtimestamp");
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ appendStringInfoString(str, "localtimestamp"); // with precision
+ break;
+ case SVFOP_CURRENT_ROLE:
+ appendStringInfoString(str, "current_role");
+ break;
+ case SVFOP_CURRENT_USER:
+ appendStringInfoString(str, "current_user");
+ break;
+ case SVFOP_USER:
+ appendStringInfoString(str, "user");
+ break;
+ case SVFOP_SESSION_USER:
+ appendStringInfoString(str, "session_user");
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ appendStringInfoString(str, "current_catalog");
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ appendStringInfoString(str, "current_schema");
+ break;
+ }
+
+ if (sql_value_function->typmod != -1)
+ {
+ appendStringInfo(str, "(%d)", sql_value_function->typmod);
+ }
+}
+
+static void deparseWithClause(StringInfo str, WithClause *with_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "WITH ");
+ if (with_clause->recursive)
+ appendStringInfoString(str, "RECURSIVE ");
+
+ foreach(lc, with_clause->ctes) {
+ deparseCommonTableExpr(str, castNode(CommonTableExpr, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
+{
+ ListCell *lc;
+ bool need_alias_parens = join_expr->alias != NULL;
+ bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
+
+ if (need_alias_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseTableRef(str, join_expr->larg);
+
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->isNatural)
+ appendStringInfoString(str, "NATURAL ");
+
+ switch (join_expr->jointype)
+ {
+ case JOIN_INNER: /* matching tuple pairs only */
+ if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
+ appendStringInfoString(str, "CROSS ");
+ break;
+ case JOIN_LEFT: /* pairs + unmatched LHS tuples */
+ appendStringInfoString(str, "LEFT ");
+ break;
+ case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
+ appendStringInfoString(str, "FULL ");
+ break;
+ case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
+ appendStringInfoString(str, "RIGHT ");
+ break;
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ case JOIN_UNIQUE_OUTER:
+ case JOIN_UNIQUE_INNER:
+ // Only used by the planner/executor, not seen in parser output
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "JOIN ");
+
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseTableRef(str, join_expr->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->quals != NULL)
+ {
+ appendStringInfoString(str, "ON ");
+ deparseExpr(str, join_expr->quals);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(join_expr->usingClause) > 0)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseNameList(str, join_expr->usingClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (need_alias_parens)
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->alias != NULL)
+ deparseAlias(str, join_expr->alias);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
+{
+ deparseColId(str, cte->ctename);
+
+ if (list_length(cte->aliascolnames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, cte->aliascolnames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ switch (cte->ctematerialized) {
+ case CTEMaterializeDefault: /* no option specified */
+ break;
+ case CTEMaterializeAlways:
+ appendStringInfoString(str, "MATERIALIZED ");
+ break;
+ case CTEMaterializeNever:
+ appendStringInfoString(str, "NOT MATERIALIZED ");
+ break;
+ }
+
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, cte->ctequery);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
+{
+ if (range_subselect->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, range_subselect->subquery));
+ appendStringInfoChar(str, ')');
+
+ if (range_subselect->alias != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseAlias(str, range_subselect->alias);
+ }
+}
+
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (range_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ if (range_func->is_rowsfrom)
+ {
+ appendStringInfoString(str, "ROWS FROM ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->functions)
+ {
+ List *lfunc = castNode(List, lfirst(lc));
+ Assert(list_length(lfunc) == 2);
+ deparseFuncExprWindowless(str, linitial(lfunc));
+ appendStringInfoChar(str, ' ');
+ List *coldeflist = castNode(List, lsecond(lfunc));
+ if (list_length(coldeflist) > 0)
+ {
+ appendStringInfoString(str, "AS (");
+ foreach(lc2, coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc2)));
+ if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(list_length(linitial(range_func->functions)) == 2);
+ deparseFuncExprWindowless(str, linitial(linitial(range_func->functions)));
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (range_func->ordinality)
+ appendStringInfoString(str, "WITH ORDINALITY ");
+
+ if (range_func->alias != NULL)
+ {
+ deparseAlias(str, range_func->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(range_func->coldeflist) > 0)
+ {
+ if (range_func->alias == NULL)
+ appendStringInfoString(str, "AS ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr *array_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ARRAY[");
+ deparseExprList(str, array_expr->elements);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
+{
+ ListCell *lc;
+
+ switch (row_expr->row_format)
+ {
+ case COERCE_EXPLICIT_CALL:
+ appendStringInfoString(str, "ROW");
+ break;
+ case COERCE_EXPLICIT_CAST:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCE_IMPLICIT_CAST:
+ // No prefix
+ break;
+ }
+
+ appendStringInfoString(str, "(");
+ deparseExprList(str, row_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
+{
+ bool need_parens = false;
+
+ Assert(type_cast->typeName != NULL);
+
+ if (IsA(type_cast->arg, A_Expr))
+ {
+ appendStringInfoString(str, "CAST(");
+ deparseExpr(str, type_cast->arg);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, type_cast->typeName);
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ if (IsA(type_cast->arg, A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, type_cast->arg);
+
+ if (list_length(type_cast->typeName->names) == 2 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
+ {
+ char *typename = strVal(lsecond(type_cast->typeName->names));
+ if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
+ {
+ appendStringInfoString(str, "char ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
+ {
+ /*
+ * Handle "bool" or "false" in the statement, which is represented as a typecast
+ * (other boolean casts should be represented as a cast, i.e. don't need special handling)
+ */
+ char *const_val = strVal(&a_const->val);
+ if (strcmp(const_val, "t") == 0)
+ {
+ appendStringInfoString(str, "true");
+ return;
+ }
+ if (strcmp(const_val, "f") == 0)
+ {
+ appendStringInfoString(str, "false");
+ return;
+ }
+ }
+ }
+
+ // Ensure negative values have wrapping parentheses
+ if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
+ {
+ need_parens = true;
+ }
+ }
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, type_cast->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, "::");
+ deparseTypeName(str, type_cast->typeName);
+}
+
+static void deparseTypeName(StringInfo str, TypeName *type_name)
+{
+ ListCell *lc;
+ bool skip_typmods = false;
+
+ if (type_name->setof)
+ appendStringInfoString(str, "SETOF ");
+
+ if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
+ {
+ const char *name = strVal(lsecond(type_name->names));
+ if (strcmp(name, "bpchar") == 0)
+ {
+ appendStringInfoString(str, "char");
+ }
+ else if (strcmp(name, "varchar") == 0)
+ {
+ appendStringInfoString(str, "varchar");
+ }
+ else if (strcmp(name, "numeric") == 0)
+ {
+ appendStringInfoString(str, "numeric");
+ }
+ else if (strcmp(name, "bool") == 0)
+ {
+ appendStringInfoString(str, "boolean");
+ }
+ else if (strcmp(name, "int2") == 0)
+ {
+ appendStringInfoString(str, "smallint");
+ }
+ else if (strcmp(name, "int4") == 0)
+ {
+ appendStringInfoString(str, "int");
+ }
+ else if (strcmp(name, "int8") == 0)
+ {
+ appendStringInfoString(str, "bigint");
+ }
+ else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
+ {
+ appendStringInfoString(str, "real");
+ }
+ else if (strcmp(name, "float8") == 0)
+ {
+ appendStringInfoString(str, "double precision");
+ }
+ else if (strcmp(name, "time") == 0)
+ {
+ appendStringInfoString(str, "time");
+ }
+ else if (strcmp(name, "timetz") == 0)
+ {
+ appendStringInfoString(str, "time ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "timestamp") == 0)
+ {
+ appendStringInfoString(str, "timestamp");
+ }
+ else if (strcmp(name, "timestamptz") == 0)
+ {
+ appendStringInfoString(str, "timestamp ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
+ {
+ appendStringInfoString(str, "interval");
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
+ {
+ Assert(IsA(linitial(type_name->typmods), A_Const));
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
+
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
+
+ appendStringInfoString(str, "interval");
+
+ // This logic is based on intervaltypmodout in timestamp.c
+ switch (fields)
+ {
+ case INTERVAL_MASK(YEAR):
+ appendStringInfoString(str, " year");
+ break;
+ case INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " month");
+ break;
+ case INTERVAL_MASK(DAY):
+ appendStringInfoString(str, " day");
+ break;
+ case INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " hour");
+ break;
+ case INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " minute");
+ break;
+ case INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " second");
+ break;
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " year to month");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " day to hour");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " day to minute");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " day to second");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " hour to minute");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " hour to second");
+ break;
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " minute to second");
+ break;
+ case INTERVAL_FULL_RANGE:
+ // Nothing
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (list_length(type_name->typmods) == 2)
+ {
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
+ if (precision != INTERVAL_FULL_PRECISION)
+ appendStringInfo(str, "(%d)", precision);
+ }
+
+ skip_typmods = true;
+ }
+ else
+ {
+ appendStringInfoString(str, "pg_catalog.");
+ appendStringInfoString(str, name);
+ }
+ }
+ else
+ {
+ deparseAnyName(str, type_name->names);
+ }
+
+ if (list_length(type_name->typmods) > 0 && !skip_typmods)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ if (IsA(lfirst(lc), A_Const))
+ deparseAConst(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ParamRef))
+ deparseParamRef(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ColumnRef))
+ deparseColumnRef(str, lfirst(lc));
+ else
+ Assert(false);
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ foreach(lc, type_name->arrayBounds)
+ {
+ appendStringInfoChar(str, '[');
+ if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
+ deparseSignedIconst(str, lfirst(lc));
+ appendStringInfoChar(str, ']');
+ }
+
+ if (type_name->pct_type)
+ appendStringInfoString(str, "%type");
+}
+
+static void deparseNullTest(StringInfo str, NullTest *null_test)
+{
+ // argisrow is always false in raw parser output
+ Assert(null_test->argisrow == false);
+
+ deparseExpr(str, (Node *) null_test->arg);
+ switch (null_test->nulltesttype)
+ {
+ case IS_NULL:
+ appendStringInfoString(str, " IS NULL");
+ break;
+ case IS_NOT_NULL:
+ appendStringInfoString(str, " IS NOT NULL");
+ break;
+ }
+}
+
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CASE ");
+
+ if (case_expr->arg != NULL)
+ {
+ deparseExpr(str, (Node *) case_expr->arg);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, case_expr->args)
+ {
+ deparseCaseWhen(str, castNode(CaseWhen, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (case_expr->defresult != NULL)
+ {
+ appendStringInfoString(str, "ELSE ");
+ deparseExpr(str, (Node *) case_expr->defresult);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "END");
+}
+
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when)
+{
+ appendStringInfoString(str, "WHEN ");
+ deparseExpr(str, (Node *) case_when->expr);
+ appendStringInfoString(str, " THEN ");
+ deparseExpr(str, (Node *) case_when->result);
+}
+
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection)
+{
+ ListCell *lc;
+ bool need_parens =
+ IsA(a_indirection->arg, A_Indirection) ||
+ IsA(a_indirection->arg, FuncCall) ||
+ IsA(a_indirection->arg, A_Expr) ||
+ IsA(a_indirection->arg, TypeCast) ||
+ IsA(a_indirection->arg, RowExpr) ||
+ (IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices));
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, a_indirection->arg);
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ deparseOptIndirection(str, a_indirection->indirection, 0);
+}
+
+static void deparseAIndices(StringInfo str, A_Indices *a_indices)
+{
+ appendStringInfoChar(str, '[');
+ if (a_indices->lidx != NULL)
+ deparseExpr(str, a_indices->lidx);
+ if (a_indices->is_slice)
+ appendStringInfoChar(str, ':');
+ if (a_indices->uidx != NULL)
+ deparseExpr(str, a_indices->uidx);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr)
+{
+ appendStringInfoString(str, "COALESCE(");
+ deparseExprList(str, coalesce_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr)
+{
+ switch (min_max_expr->op)
+ {
+ case IS_GREATEST:
+ appendStringInfoString(str, "GREATEST(");
+ break;
+ case IS_LEAST:
+ appendStringInfoString(str, "LEAST(");
+ break;
+ }
+ deparseExprList(str, min_max_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test)
+{
+ deparseExpr(str, (Node *) boolean_test->arg);
+ switch (boolean_test->booltesttype)
+ {
+ case IS_TRUE:
+ appendStringInfoString(str, " IS TRUE");
+ break;
+ case IS_NOT_TRUE:
+ appendStringInfoString(str, " IS NOT TRUE");
+ break;
+ case IS_FALSE:
+ appendStringInfoString(str, " IS FALSE");
+ break;
+ case IS_NOT_FALSE:
+ appendStringInfoString(str, " IS NOT FALSE");
+ break;
+ case IS_UNKNOWN:
+ appendStringInfoString(str, " IS UNKNOWN");
+ break;
+ case IS_NOT_UNKNOWN:
+ appendStringInfoString(str, " IS NOT UNKNOWN");
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
+{
+ ListCell *lc;
+
+ if (column_def->colname != NULL)
+ {
+ appendStringInfoString(str, column_def->colname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->typeName != NULL)
+ {
+ deparseTypeName(str, column_def->typeName);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->raw_default != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseExpr(str, column_def->raw_default);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->fdwoptions != NULL)
+ {
+ deparseCreateGenericOptions(str, column_def->fdwoptions);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, column_def->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->collClause != NULL)
+ {
+ deparseCollateClause(str, column_def->collClause);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (insert_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, insert_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "INSERT INTO ");
+ deparseRangeVar(str, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(insert_stmt->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseInsertColumnList(str, insert_stmt->cols);
+ appendStringInfoString(str, ") ");
+ }
+
+ switch (insert_stmt->override)
+ {
+ case OVERRIDING_NOT_SET:
+ // Do nothing
+ break;
+ case OVERRIDING_USER_VALUE:
+ appendStringInfoString(str, "OVERRIDING USER VALUE ");
+ break;
+ case OVERRIDING_SYSTEM_VALUE:
+ appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
+ break;
+ }
+
+ if (insert_stmt->selectStmt != NULL)
+ {
+ deparseSelectStmt(str, castNode(SelectStmt, insert_stmt->selectStmt));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "DEFAULT VALUES ");
+ }
+
+ if (insert_stmt->onConflictClause != NULL)
+ {
+ deparseOnConflictClause(str, insert_stmt->onConflictClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(insert_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, insert_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInferClause(StringInfo str, InferClause *infer_clause)
+{
+ ListCell *lc;
+
+ if (list_length(infer_clause->indexElems) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, infer_clause->indexElems)
+ {
+ deparseIndexElem(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ if (infer_clause->conname != NULL)
+ {
+ appendStringInfoString(str, "ON CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(infer_clause->conname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, infer_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ON CONFLICT ");
+
+ if (on_conflict_clause->infer != NULL)
+ {
+ deparseInferClause(str, on_conflict_clause->infer);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (on_conflict_clause->action)
+ {
+ case ONCONFLICT_NONE:
+ Assert(false);
+ break;
+ case ONCONFLICT_NOTHING:
+ appendStringInfoString(str, "DO NOTHING ");
+ break;
+ case ONCONFLICT_UPDATE:
+ appendStringInfoString(str, "DO UPDATE ");
+ break;
+ }
+
+ if (list_length(on_conflict_clause->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, on_conflict_clause->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, on_conflict_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
+{
+ ListCell* lc;
+ ListCell* lc2;
+ ListCell* lc3;
+
+ if (update_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, update_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "UPDATE ");
+ deparseRangeVar(str, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(update_stmt->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, update_stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, update_stmt->fromClause);
+ deparseWhereClause(str, update_stmt->whereClause);
+
+ if (list_length(update_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, update_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
+{
+ if (delete_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, delete_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "DELETE FROM ");
+ deparseRangeVar(str, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (delete_stmt->usingClause != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseFromList(str, delete_stmt->usingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, delete_stmt->whereClause);
+
+ if (list_length(delete_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, delete_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause)
+{
+ ListCell *lc;
+
+ switch (locking_clause->strength)
+ {
+ case LCS_NONE:
+ /* no such clause - only used in PlanRowMark */
+ Assert(false);
+ break;
+ case LCS_FORKEYSHARE:
+ appendStringInfoString(str, "FOR KEY SHARE ");
+ break;
+ case LCS_FORSHARE:
+ appendStringInfoString(str, "FOR SHARE ");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ appendStringInfoString(str, "FOR NO KEY UPDATE ");
+ break;
+ case LCS_FORUPDATE:
+ appendStringInfoString(str, "FOR UPDATE ");
+ break;
+ }
+
+ if (list_length(locking_clause->lockedRels) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseQualifiedNameList(str, locking_clause->lockedRels);
+ }
+
+ switch (locking_clause->waitPolicy)
+ {
+ case LockWaitError:
+ appendStringInfoString(str, "NOWAIT");
+ break;
+ case LockWaitSkip:
+ appendStringInfoString(str, "SKIP LOCKED");
+ break;
+ case LockWaitBlock:
+ // Default
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default)
+{
+ appendStringInfoString(str, "DEFAULT");
+}
+
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ appendStringInfoString(str, "CREATE CAST (");
+ deparseTypeName(str, create_cast_stmt->sourcetype);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, create_cast_stmt->targettype);
+ appendStringInfoString(str, ") ");
+
+ if (create_cast_stmt->func != NULL)
+ {
+ appendStringInfoString(str, "WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_cast_stmt->func);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_cast_stmt->inout)
+ {
+ appendStringInfoString(str, "WITH INOUT ");
+ }
+ else
+ {
+ appendStringInfoString(str, "WITHOUT FUNCTION ");
+ }
+
+ switch (create_cast_stmt->context)
+ {
+ case COERCION_IMPLICIT:
+ appendStringInfoString(str, "AS IMPLICIT");
+ break;
+ case COERCION_ASSIGNMENT:
+ appendStringInfoString(str, "AS ASSIGNMENT");
+ break;
+ case COERCION_EXPLICIT:
+ // Default
+ break;
+ }
+}
+
+static void deparseCreateOpClassStmt(StringInfo str, CreateOpClassStmt *create_op_class_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE OPERATOR CLASS ");
+
+ deparseAnyName(str, create_op_class_stmt->opclassname);
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->isDefault)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, create_op_class_stmt->datatype);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_class_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->opfamilyname != NULL)
+ {
+ appendStringInfoString(str, "FAMILY ");
+ deparseAnyName(str, create_op_class_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "AS ");
+ deparseOpclassItemList(str, create_op_class_stmt->items);
+}
+
+static void deparseCreateOpFamilyStmt(StringInfo str, CreateOpFamilyStmt *create_op_family_stmt)
+{
+ appendStringInfoString(str, "CREATE OPERATOR FAMILY ");
+
+ deparseAnyName(str, create_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_family_stmt->amname));
+}
+
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item)
+{
+ ListCell *lc = NULL;
+
+ switch (create_op_class_item->itemtype)
+ {
+ case OPCLASS_ITEM_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+
+ if (create_op_class_item->name != NULL)
+ {
+ if (create_op_class_item->name->objargs != NULL)
+ deparseOperatorWithArgtypes(str, create_op_class_item->name);
+ else
+ deparseAnyOperator(str, create_op_class_item->name->objname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_op_class_item->order_family != NULL)
+ {
+ appendStringInfoString(str, "FOR ORDER BY ");
+ deparseAnyName(str, create_op_class_item->order_family);
+ }
+
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoChar(str, ')');
+ }
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoString(str, ") ");
+ }
+ if (create_op_class_item->name != NULL)
+ deparseFunctionWithArgtypes(str, create_op_class_item->name);
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_STORAGETYPE:
+ appendStringInfoString(str, "STORAGE ");
+ deparseTypeName(str, create_op_class_item->storedtype);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseTableLikeClause(StringInfo str, TableLikeClause *table_like_clause)
+{
+ appendStringInfoString(str, "LIKE ");
+ deparseRangeVar(str, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
+ appendStringInfoString(str, "INCLUDING ALL ");
+ else
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+ appendStringInfoString(str, "INCLUDING COMMENTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ appendStringInfoString(str, "INCLUDING CONSTRAINTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
+ appendStringInfoString(str, "INCLUDING DEFAULTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
+ appendStringInfoString(str, "INCLUDING IDENTITY ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED)
+ appendStringInfoString(str, "INCLUDING GENERATED ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ appendStringInfoString(str, "INCLUDING INDEXES ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
+ appendStringInfoString(str, "INCLUDING STATISTICS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ appendStringInfoString(str, "INCLUDING STORAGE ");
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt)
+{
+ ListCell *lc;
+
+ Assert(create_domain_stmt->typeName != NULL);
+
+ appendStringInfoString(str, "CREATE DOMAIN ");
+ deparseAnyName(str, create_domain_stmt->domainname);
+ appendStringInfoString(str, " AS ");
+
+ deparseTypeName(str, create_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (create_domain_stmt->collClause != NULL)
+ {
+ deparseCollateClause(str, create_domain_stmt->collClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_domain_stmt->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateExtensionStmt(StringInfo str, CreateExtensionStmt *create_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE EXTENSION ");
+
+ if (create_extension_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseColId(str, create_extension_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, create_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "schema") == 0)
+ {
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "cascade") == 0)
+ {
+ appendStringInfoString(str, "CASCADE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraint(StringInfo str, Constraint *constraint)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, constraint->conname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (constraint->contype) {
+ case CONSTR_NULL:
+ appendStringInfoString(str, "NULL ");
+ break;
+ case CONSTR_NOTNULL:
+ appendStringInfoString(str, "NOT NULL ");
+ break;
+ case CONSTR_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, constraint->raw_expr);
+ break;
+ case CONSTR_IDENTITY:
+ appendStringInfoString(str, "GENERATED ");
+ switch (constraint->generated_when)
+ {
+ case ATTRIBUTE_IDENTITY_ALWAYS:
+ appendStringInfoString(str, "ALWAYS ");
+ break;
+ case ATTRIBUTE_IDENTITY_BY_DEFAULT:
+ appendStringInfoString(str, "BY DEFAULT ");
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoString(str, "AS IDENTITY ");
+ deparseOptParenthesizedSeqOptList(str, constraint->options);
+ break;
+ case CONSTR_GENERATED:
+ Assert(constraint->generated_when == ATTRIBUTE_IDENTITY_ALWAYS);
+ appendStringInfoString(str, "GENERATED ALWAYS AS (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") STORED ");
+ break;
+ case CONSTR_CHECK:
+ appendStringInfoString(str, "CHECK (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") ");
+ break;
+ case CONSTR_PRIMARY:
+ appendStringInfoString(str, "PRIMARY KEY ");
+ break;
+ case CONSTR_UNIQUE:
+ appendStringInfoString(str, "UNIQUE ");
+ break;
+ case CONSTR_EXCLUSION:
+ appendStringInfoString(str, "EXCLUDE ");
+ if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(constraint->access_method));
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoChar(str, '(');
+ foreach(lc, constraint->exclusions)
+ {
+ List *exclusion = castNode(List, lfirst(lc));
+ Assert(list_length(exclusion) == 2);
+ deparseIndexElem(str, castNode(IndexElem, linitial(exclusion)));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyOperator(str, castNode(List, lsecond(exclusion)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ if (constraint->where_clause != NULL)
+ {
+ appendStringInfoString(str, "WHERE (");
+ deparseExpr(str, constraint->where_clause);
+ appendStringInfoString(str, ") ");
+ }
+ break;
+ case CONSTR_FOREIGN:
+ if (list_length(constraint->fk_attrs) > 0)
+ appendStringInfoString(str, "FOREIGN KEY ");
+ break;
+ case CONSTR_ATTR_DEFERRABLE:
+ appendStringInfoString(str, "DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ appendStringInfoString(str, "NOT DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_DEFERRED:
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+ break;
+ case CONSTR_ATTR_IMMEDIATE:
+ appendStringInfoString(str, "INITIALLY IMMEDIATE ");
+ break;
+ }
+
+ if (list_length(constraint->keys) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->keys);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (list_length(constraint->fk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->fk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->pktable != NULL)
+ {
+ appendStringInfoString(str, "REFERENCES ");
+ deparseRangeVar(str, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ if (list_length(constraint->pk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->pk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ switch (constraint->fk_matchtype)
+ {
+ case FKCONSTR_MATCH_SIMPLE:
+ // Default
+ break;
+ case FKCONSTR_MATCH_FULL:
+ appendStringInfoString(str, "MATCH FULL ");
+ break;
+ case FKCONSTR_MATCH_PARTIAL:
+ // Not implemented in Postgres
+ Assert(false);
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_upd_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON UPDATE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON UPDATE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON UPDATE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON UPDATE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_del_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON DELETE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON DELETE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON DELETE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON DELETE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ if (list_length(constraint->including) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ deparseColumnList(str, constraint->including);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->indexname != NULL)
+ appendStringInfo(str, "USING INDEX %s ", quote_identifier(constraint->indexname));
+
+ if (constraint->indexspace != NULL)
+ appendStringInfo(str, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
+
+ if (constraint->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (constraint->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (constraint->is_no_inherit)
+ appendStringInfoString(str, "NO INHERIT ");
+
+ if (constraint->skip_validation)
+ appendStringInfoString(str, "NOT VALID ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
+{
+ ListCell *lc;
+ bool tableFunc = false;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_function_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_function_stmt->is_procedure)
+ appendStringInfoString(str, "PROCEDURE ");
+ else
+ appendStringInfoString(str, "FUNCTION ");
+
+ deparseFuncName(str, create_function_stmt->funcname);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode != FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(lc) && castNode(FunctionParameter, lfirst(lnext(lc)))->mode != FUNC_PARAM_TABLE)
+ appendStringInfoString(str, ", ");
+ }
+ else
+ {
+ tableFunc = true;
+ }
+ }
+ appendStringInfoString(str, ") ");
+
+ if (tableFunc)
+ {
+ appendStringInfoString(str, "RETURNS TABLE (");
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode == FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_function_stmt->returnType != NULL)
+ {
+ appendStringInfoString(str, "RETURNS ");
+ deparseTypeName(str, create_function_stmt->returnType);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_function_stmt->options)
+ {
+ deparseCreateFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter)
+{
+ switch (function_parameter->mode)
+ {
+ case FUNC_PARAM_IN: /* input only */
+ // Default
+ break;
+ case FUNC_PARAM_OUT: /* output only */
+ appendStringInfoString(str, "OUT ");
+ break;
+ case FUNC_PARAM_INOUT: /* both */
+ appendStringInfoString(str, "INOUT ");
+ break;
+ case FUNC_PARAM_VARIADIC: /* variadic (always input) */
+ appendStringInfoString(str, "VARIADIC ");
+ break;
+ case FUNC_PARAM_TABLE: /* table function output column */
+ // No special annotation, the caller is expected to correctly put
+ // this into the RETURNS part of the CREATE FUNCTION statement
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (function_parameter->name != NULL)
+ {
+ appendStringInfoString(str, function_parameter->name);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseTypeName(str, function_parameter->argType);
+ appendStringInfoChar(str, ' ');
+
+ if (function_parameter->defexpr != NULL)
+ {
+ appendStringInfoString(str, "= ");
+ deparseExpr(str, function_parameter->defexpr);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_stmt)
+{
+ appendStringInfoString(str, "CHECKPOINT");
+}
+
+static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SCHEMA ");
+
+ if (create_schema_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (create_schema_stmt->schemaname)
+ {
+ deparseColId(str, create_schema_stmt->schemaname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->authrole != NULL)
+ {
+ appendStringInfoString(str, "AUTHORIZATION ");
+ deparseRoleSpec(str, create_schema_stmt->authrole);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_schema_stmt->schemaElts)
+ {
+ deparseSchemaStmt(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleSetStmt(StringInfo str, AlterRoleSetStmt *alter_role_set_stmt)
+{
+ appendStringInfoString(str, "ALTER ROLE ");
+
+ if (alter_role_set_stmt->role == NULL)
+ appendStringInfoString(str, "ALL");
+ else
+ deparseRoleSpec(str, alter_role_set_stmt->role);
+
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_set_stmt->database != NULL)
+ {
+ appendStringInfoString(str, "IN DATABASE ");
+ appendStringInfoString(str, quote_identifier(alter_role_set_stmt->database));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseVariableSetStmt(str, alter_role_set_stmt->setstmt);
+}
+
+static void deparseCreateConversionStmt(StringInfo str, CreateConversionStmt *create_conversion_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_conversion_stmt->def)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, create_conversion_stmt->conversion_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "FOR ");
+ deparseStringLiteral(str, create_conversion_stmt->for_encoding_name);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, create_conversion_stmt->to_encoding_name);
+
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, create_conversion_stmt->func_name);
+}
+
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
+{
+ switch (role_spec->roletype)
+ {
+ case ROLESPEC_CSTRING:
+ Assert(role_spec->rolename != NULL);
+ appendStringInfoString(str, quote_identifier(role_spec->rolename));
+ break;
+ case ROLESPEC_CURRENT_USER:
+ appendStringInfoString(str, "CURRENT_USER");
+ break;
+ case ROLESPEC_SESSION_USER:
+ appendStringInfoString(str, "SESSION_USER");
+ break;
+ case ROLESPEC_PUBLIC:
+ appendStringInfoString(str, "public");
+ break;
+ }
+}
+
+// "part_elem" in gram.y
+static void deparsePartitionElem(StringInfo str, PartitionElem *partition_elem)
+{
+ ListCell *lc;
+
+ if (partition_elem->name != NULL)
+ {
+ deparseColId(str, partition_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (partition_elem->expr != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, partition_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptCollate(str, partition_elem->collation);
+ deparseAnyName(str, partition_elem->opclass);
+
+ removeTrailingSpace(str);
+}
+
+static void deparsePartitionSpec(StringInfo str, PartitionSpec *partition_spec)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "PARTITION BY ");
+ appendStringInfoString(str, partition_spec->strategy);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, partition_spec->partParams)
+ {
+ deparsePartitionElem(str, castNode(PartitionElem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparsePartitionBoundSpec(StringInfo str, PartitionBoundSpec *partition_bound_spec)
+{
+ ListCell *lc;
+
+ if (partition_bound_spec->is_default)
+ {
+ appendStringInfoString(str, "DEFAULT");
+ return;
+ }
+
+ appendStringInfoString(str, "FOR VALUES ");
+
+ switch (partition_bound_spec->strategy)
+ {
+ case PARTITION_STRATEGY_HASH:
+ appendStringInfo(str, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
+ break;
+ case PARTITION_STRATEGY_LIST:
+ appendStringInfoString(str, "IN (");
+ deparseExprList(str, partition_bound_spec->listdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ appendStringInfoString(str, "FROM (");
+ deparseExprList(str, partition_bound_spec->lowerdatums);
+ appendStringInfoString(str, ") TO (");
+ deparseExprList(str, partition_bound_spec->upperdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
+{
+ deparseRangeVar(str, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (partition_cmd->bound != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparsePartitionBoundSpec(str, partition_cmd->bound);
+ }
+}
+
+// "TableElement" in gram.y
+static void deparseTableElement(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnDef:
+ deparseColumnDef(str, castNode(ColumnDef, node));
+ break;
+ case T_TableLikeClause:
+ deparseTableLikeClause(str, castNode(TableLikeClause, node));
+ break;
+ case T_Constraint:
+ deparseConstraint(str, castNode(Constraint, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseCreateStmt(StringInfo str, CreateStmt *create_stmt, bool is_foreign_table)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (is_foreign_table)
+ appendStringInfoString(str, "FOREIGN ");
+
+ deparseOptTemp(str, create_stmt->relation->relpersistence);
+
+ appendStringInfoString(str, "TABLE ");
+
+ if (create_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_stmt->ofTypename != NULL)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseTypeName(str, create_stmt->ofTypename);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ Assert(list_length(create_stmt->inhRelations) == 1);
+ appendStringInfoString(str, "PARTITION OF ");
+ deparseRangeVar(str, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(create_stmt->tableElts) > 0)
+ {
+ // In raw parse output tableElts contains both columns and constraints
+ // (and the constraints field is NIL)
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_stmt->tableElts)
+ {
+ deparseTableElement(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
+ {
+ appendStringInfoString(str, "() ");
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ deparsePartitionBoundSpec(str, create_stmt->partbound);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ deparseOptInherit(str, create_stmt->inhRelations);
+ }
+
+ if (create_stmt->partspec != NULL)
+ {
+ deparsePartitionSpec(str, create_stmt->partspec);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_stmt->accessMethod));
+ }
+
+ deparseOptWith(str, create_stmt->options);
+
+ switch (create_stmt->oncommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No ON COMMIT clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (create_stmt->tablespacename != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(create_stmt->tablespacename));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFdwStmt(StringInfo str, CreateFdwStmt *create_fdw_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, create_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseCreateGenericOptions(str, create_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFdwStmt(StringInfo str, AlterFdwStmt *alter_fdw_stmt)
+{
+ appendStringInfoString(str, "ALTER FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(alter_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, alter_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_fdw_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateForeignServerStmt(StringInfo str, CreateForeignServerStmt *create_foreign_server_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SERVER ");
+ if (create_foreign_server_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (create_foreign_server_stmt->servertype != NULL)
+ {
+ appendStringInfoString(str, "TYPE ");
+ deparseStringLiteral(str, create_foreign_server_stmt->servertype);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_foreign_server_stmt->version != NULL)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseStringLiteral(str, create_foreign_server_stmt->version);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterForeignServerStmt(StringInfo str, AlterForeignServerStmt *alter_foreign_server_stmt)
+{
+ appendStringInfoString(str, "ALTER SERVER ");
+
+ appendStringInfoString(str, quote_identifier(alter_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_foreign_server_stmt->has_version)
+ {
+ appendStringInfoString(str, "VERSION ");
+ if (alter_foreign_server_stmt->version != NULL)
+ deparseStringLiteral(str, alter_foreign_server_stmt->version);
+ else
+ appendStringInfoString(str, "NULL");
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_foreign_server_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateUserMappingStmt(StringInfo str, CreateUserMappingStmt *create_user_mapping_stmt)
+{
+ appendStringInfoString(str, "CREATE USER MAPPING ");
+ if (create_user_mapping_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, create_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(create_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreatedbStmt(StringInfo str, CreatedbStmt *createdb_stmt)
+{
+ appendStringInfoString(str, "CREATE DATABASE ");
+ deparseColId(str, createdb_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, createdb_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterUserMappingStmt(StringInfo str, AlterUserMappingStmt *alter_user_mapping_stmt)
+{
+ appendStringInfoString(str, "ALTER USER MAPPING FOR ");
+ deparseRoleSpec(str, alter_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(alter_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseAlterGenericOptions(str, alter_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropUserMappingStmt(StringInfo str, DropUserMappingStmt *drop_user_mapping_stmt)
+{
+ appendStringInfoString(str, "DROP USER MAPPING ");
+
+ if (drop_user_mapping_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, drop_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(drop_user_mapping_stmt->servername));
+}
+
+static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "SECURITY LABEL ");
+
+ if (sec_label_stmt->provider != NULL)
+ {
+ appendStringInfoString(str, "FOR ");
+ appendStringInfoString(str, quote_identifier(sec_label_stmt->provider));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ switch (sec_label_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseValue(str, (Value *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ default:
+ // Not supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (sec_label_stmt->label != NULL)
+ deparseStringLiteral(str, sec_label_stmt->label);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateForeignTableStmt(StringInfo str, CreateForeignTableStmt *create_foreign_table_stmt)
+{
+ ListCell *lc;
+
+ deparseCreateStmt(str, &create_foreign_table_stmt->base, true);
+
+ appendStringInfoString(str, " SERVER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_table_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_foreign_table_stmt->options) > 0)
+ deparseAlterGenericOptions(str, create_foreign_table_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseImportForeignSchemaStmt(StringInfo str, ImportForeignSchemaStmt *import_foreign_schema_stmt)
+{
+ appendStringInfoString(str, "IMPORT FOREIGN SCHEMA ");
+
+ appendStringInfoString(str, import_foreign_schema_stmt->remote_schema);
+ appendStringInfoChar(str, ' ');
+
+ switch (import_foreign_schema_stmt->list_type)
+ {
+ case FDW_IMPORT_SCHEMA_ALL:
+ // Default
+ break;
+ case FDW_IMPORT_SCHEMA_LIMIT_TO:
+ appendStringInfoString(str, "LIMIT TO (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ case FDW_IMPORT_SCHEMA_EXCEPT:
+ appendStringInfoString(str, "EXCEPT (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ }
+
+ appendStringInfoString(str, "FROM SERVER ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->server_name));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "INTO ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->local_schema));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, import_foreign_schema_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_table_as_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
+
+ switch (create_table_as_stmt->relkind)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ if (create_table_as_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseIntoClause(str, create_table_as_stmt->into);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ if (IsA(create_table_as_stmt->query, ExecuteStmt))
+ deparseExecuteStmt(str, castNode(ExecuteStmt, create_table_as_stmt->query));
+ else
+ deparseSelectStmt(str, castNode(SelectStmt, create_table_as_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_as_stmt->into->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (view_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ deparseOptTemp(str, view_stmt->view->relpersistence);
+
+ appendStringInfoString(str, "VIEW ");
+ deparseRangeVar(str, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(view_stmt->aliases) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, view_stmt->aliases);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, view_stmt->options);
+
+ appendStringInfoString(str, "AS ");
+ deparseSelectStmt(str, castNode(SelectStmt, view_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ switch (view_stmt->withCheckOption)
+ {
+ case NO_CHECK_OPTION:
+ // Default
+ break;
+ case LOCAL_CHECK_OPTION:
+ appendStringInfoString(str, "WITH LOCAL CHECK OPTION ");
+ break;
+ case CASCADED_CHECK_OPTION:
+ appendStringInfoString(str, "WITH CHECK OPTION ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "DROP ");
+
+ switch (drop_stmt->removeType)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ default:
+ // Other object types are not supported here in the parser
+ Assert(false);
+ }
+
+ if (drop_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (drop_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (drop_stmt->removeType)
+ {
+ // drop_type_any_name
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ deparseAnyNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name_on_any_name
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseColId(str, strVal(llast(l)));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_CAST:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TRANSFORM:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_LANGUAGE:
+ deparseStringLiteral(str, strVal(linitial(drop_stmt->objects)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_AGGREGATE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPERATOR:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseOptDropBehavior(str, drop_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set)
+{
+ switch(grouping_set->kind)
+ {
+ case GROUPING_SET_EMPTY:
+ appendStringInfoString(str, "()");
+ break;
+ case GROUPING_SET_SIMPLE:
+ // Not present in raw parse trees
+ Assert(false);
+ break;
+ case GROUPING_SET_ROLLUP:
+ appendStringInfoString(str, "ROLLUP (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_CUBE:
+ appendStringInfoString(str, "CUBE (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_SETS:
+ appendStringInfoString(str, "GROUPING SETS (");
+ deparseGroupByList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ }
+}
+
+static void deparseDropTableSpaceStmt(StringInfo str, DropTableSpaceStmt *drop_table_space_stmt)
+{
+ appendStringInfoString(str, "DROP TABLESPACE ");
+
+ if (drop_table_space_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_table_space_stmt->tablespacename);
+}
+
+static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt *alter_object_depends_stmt)
+{
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_depends_stmt->objectType)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ deparseColId(str, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ // No other object types supported here
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "DEPENDS ON EXTENSION ");
+ deparseColId(str, strVal(alter_object_depends_stmt->extname));
+}
+
+static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
+{
+ List *l = NULL;
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_schema_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ appendStringInfoString(str, quote_identifier(strVal(alter_object_schema_stmt->object)));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " SET SCHEMA ");
+ appendStringInfoString(str, quote_identifier(alter_object_schema_stmt->newschema));
+}
+
+static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+ const char *options = NULL;
+ bool trailing_missing_ok = false;
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AddColumn: /* add column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ADD ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ADD COLUMN ");
+ break;
+ case AT_AddColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_ColumnDefault: /* alter column default */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ if (alter_table_cmd->def != NULL)
+ options = "SET DEFAULT";
+ else
+ options = "DROP DEFAULT";
+ break;
+ case AT_CookedColumnDefault: /* add a pre-cooked column default */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropNotNull: /* alter column drop not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP NOT NULL";
+ break;
+ case AT_SetNotNull: /* alter column set not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET NOT NULL";
+ break;
+ case AT_CheckNotNull: /* check column is already marked not null */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_SetStatistics: /* alter column set statistics */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STATISTICS";
+ break;
+ case AT_SetOptions: /* alter column set ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET";
+ break;
+ case AT_ResetOptions: /* alter column reset ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "RESET";
+ break;
+ case AT_SetStorage: /* alter column set storage */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STORAGE";
+ break;
+ case AT_DropColumn: /* drop column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "DROP ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "DROP ");
+ break;
+ case AT_DropColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndex: /* add index */
+ appendStringInfoString(str, "ADD INDEX ");
+ break;
+ case AT_ReAddIndex: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddConstraint: /* add constraint */
+ appendStringInfoString(str, "ADD ");
+ break;
+ case AT_AddConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ProcessedConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterConstraint: /* alter constraint */
+ appendStringInfoString(str, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
+ break;
+ case AT_ValidateConstraint: /* validate constraint */
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ break;
+ case AT_ValidateConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndexConstraint: /* add constraint using existing index */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropConstraint: /* drop constraint */
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ break;
+ case AT_DropConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddComment: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterColumnType: /* alter column type */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ALTER ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "TYPE";
+ break;
+ case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ // Handled via special case in def handling
+ break;
+ case AT_ChangeOwner: /* change owner */
+ appendStringInfoString(str, "OWNER TO ");
+ deparseRoleSpec(str, alter_table_cmd->newowner);
+ break;
+ case AT_ClusterOn: /* CLUSTER ON */
+ appendStringInfoString(str, "CLUSTER ON ");
+ break;
+ case AT_DropCluster: /* SET WITHOUT CLUSTER */
+ appendStringInfoString(str, "SET WITHOUT CLUSTER ");
+ break;
+ case AT_SetLogged: /* SET LOGGED */
+ appendStringInfoString(str, "SET LOGGED ");
+ break;
+ case AT_SetUnLogged: /* SET UNLOGGED */
+ appendStringInfoString(str, "SET UNLOGGED ");
+ break;
+ case AT_DropOids: /* SET WITHOUT OIDS */
+ appendStringInfoString(str, "SET WITHOUT OIDS ");
+ break;
+ case AT_SetTableSpace: /* SET TABLESPACE */
+ appendStringInfoString(str, "SET TABLESPACE ");
+ break;
+ case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
+ appendStringInfoString(str, "SET ");
+ break;
+ case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
+ appendStringInfoString(str, "RESET ");
+ break;
+ case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_EnableTrig: /* ENABLE TRIGGER name */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
+ appendStringInfoString(str, "ENABLE ALWAYS TRIGGER ");
+ break;
+ case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
+ appendStringInfoString(str, "ENABLE REPLICA TRIGGER ");
+ break;
+ case AT_DisableTrig: /* DISABLE TRIGGER name */
+ appendStringInfoString(str, "DISABLE TRIGGER ");
+ break;
+ case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
+ appendStringInfoString(str, "DISABLE TRIGGER ALL ");
+ break;
+ case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
+ appendStringInfoString(str, "ENABLE TRIGGER USER ");
+ break;
+ case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
+ appendStringInfoString(str, "DISABLE TRIGGER USER ");
+ break;
+ case AT_EnableRule: /* ENABLE RULE name */
+ appendStringInfoString(str, "ENABLE RULE ");
+ break;
+ case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
+ appendStringInfoString(str, "ENABLE ALWAYS RULE ");
+ break;
+ case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
+ appendStringInfoString(str, "ENABLE REPLICA RULE ");
+ break;
+ case AT_DisableRule: /* DISABLE RULE name */
+ appendStringInfoString(str, "DISABLE RULE ");
+ break;
+ case AT_AddInherit: /* INHERIT parent */
+ appendStringInfoString(str, "INHERIT ");
+ break;
+ case AT_DropInherit: /* NO INHERIT parent */
+ appendStringInfoString(str, "NO INHERIT ");
+ break;
+ case AT_AddOf: /* OF */
+ appendStringInfoString(str, "OF ");
+ break;
+ case AT_DropOf: /* NOT OF */
+ appendStringInfoString(str, "NOT OF ");
+ break;
+ case AT_ReplicaIdentity: /* REPLICA IDENTITY */
+ appendStringInfoString(str, "REPLICA IDENTITY ");
+ break;
+ case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
+ appendStringInfoString(str, "ENABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
+ appendStringInfoString(str, "DISABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
+ appendStringInfoString(str, "FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
+ appendStringInfoString(str, "NO FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_GenericOptions: /* OPTIONS (...) */
+ // Handled in def field handling
+ break;
+ case AT_AttachPartition: /* ATTACH PARTITION */
+ appendStringInfoString(str, "ATTACH PARTITION ");
+ break;
+ case AT_DetachPartition: /* DETACH PARTITION */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_AddIdentity: /* ADD IDENTITY */
+ appendStringInfoString(str, "ALTER ");
+ options = "ADD";
+ // Other details are output via the constraint node (in def field)
+ break;
+ case AT_SetIdentity: /* SET identity column options */
+ appendStringInfoString(str, "ALTER ");
+ break;
+ case AT_DropIdentity: /* DROP IDENTITY */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP IDENTITY";
+ trailing_missing_ok = true;
+ break;
+ }
+
+ if (alter_table_cmd->missing_ok && !trailing_missing_ok)
+ {
+ if (alter_table_cmd->subtype == AT_AddColumn)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ else
+ appendStringInfoString(str, "IF EXISTS ");
+ }
+
+ if (alter_table_cmd->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(alter_table_cmd->name));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->num > 0)
+ appendStringInfo(str, "%d ", alter_table_cmd->num);
+
+ if (options != NULL)
+ {
+ appendStringInfoString(str, options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->missing_ok && trailing_missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddColumn:
+ case AT_AlterColumnType:
+ deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ColumnDefault:
+ if (alter_table_cmd->def != NULL)
+ {
+ deparseExpr(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case AT_SetStatistics:
+ deparseSignedIconst(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetOptions:
+ case AT_ResetOptions:
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+ deparseRelOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetStorage:
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddIdentity:
+ case AT_AddConstraint:
+ case AT_AlterConstraint:
+ deparseConstraint(str, castNode(Constraint, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetIdentity:
+ deparseAlterIdentityColumnOptionList(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AlterColumnGenericOptions:
+ case AT_GenericOptions:
+ deparseAlterGenericOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddInherit:
+ case AT_DropInherit:
+ deparseRangeVar(str, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddOf:
+ deparseTypeName(str, castNode(TypeName, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ReplicaIdentity:
+ deparseReplicaIdentityStmt(str, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(alter_table_cmd->def == NULL);
+ break;
+ }
+
+ deparseOptDropBehavior(str, alter_table_cmd->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
+{
+ ListCell *lc;
+ DeparseNodeContext context = DEPARSE_NODE_CONTEXT_NONE;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_table_stmt->relkind)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ context = DEPARSE_NODE_CONTEXT_ALTER_TYPE;
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (alter_table_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_table_stmt->relation, context);
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, alter_table_stmt->cmds)
+ {
+ deparseAlterTableCmd(str, castNode(AlterTableCmd, lfirst(lc)), context);
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterTableSpaceOptionsStmt(StringInfo str, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
+{
+ appendStringInfoString(str, "ALTER TABLESPACE ");
+ deparseColId(str, alter_table_space_options_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_table_space_options_stmt->isReset)
+ appendStringInfoString(str, "RESET ");
+ else
+ appendStringInfoString(str, "SET ");
+
+ deparseRelOptions(str, alter_table_space_options_stmt->options);
+}
+
+static void deparseAlterDomainStmt(StringInfo str, AlterDomainStmt *alter_domain_stmt)
+{
+ appendStringInfoString(str, "ALTER DOMAIN ");
+ deparseAnyName(str, alter_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_domain_stmt->subtype)
+ {
+ case 'T':
+ if (alter_domain_stmt->def != NULL)
+ {
+ appendStringInfoString(str, "SET DEFAULT ");
+ deparseExpr(str, alter_domain_stmt->def);
+ }
+ else
+ {
+ appendStringInfoString(str, "DROP DEFAULT");
+ }
+ break;
+ case 'N':
+ appendStringInfoString(str, "DROP NOT NULL");
+ break;
+ case 'O':
+ appendStringInfoString(str, "SET NOT NULL");
+ break;
+ case 'C':
+ appendStringInfoString(str, "ADD ");
+ deparseConstraint(str, castNode(Constraint, alter_domain_stmt->def));
+ break;
+ case 'X':
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ if (alter_domain_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ if (alter_domain_stmt->behavior == DROP_CASCADE)
+ appendStringInfoString(str, " CASCADE");
+ break;
+ case 'V':
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ break;
+ default:
+ // No other subtypes supported by the parser
+ Assert(false);
+ }
+}
+
+static void deparseRenameStmt(StringInfo str, RenameStmt *rename_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_COLUMN:
+ switch (rename_stmt->relationType)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ Assert(false);
+ }
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_ATTRIBUTE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (rename_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, rename_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseColId(str, strVal(rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLUMN:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME COLUMN ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(strVal(rename_stmt->object)));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_DOMAIN:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TYPE:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_ATTRIBUTE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
+ appendStringInfoString(str, " RENAME ATTRIBUTE ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->newname));
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDropBehavior(str, rename_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_stmt)
+{
+ ListCell *lc;
+ switch (transaction_stmt->kind)
+ {
+ case TRANS_STMT_BEGIN:
+ appendStringInfoString(str, "BEGIN ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_START:
+ appendStringInfoString(str, "START TRANSACTION ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_COMMIT:
+ appendStringInfoString(str, "COMMIT ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_ROLLBACK:
+ appendStringInfoString(str, "ROLLBACK ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_SAVEPOINT:
+ appendStringInfoString(str, "SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_RELEASE:
+ appendStringInfoString(str, "RELEASE ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_ROLLBACK_TO:
+ appendStringInfoString(str, "ROLLBACK ");
+ appendStringInfoString(str, "TO SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_PREPARE:
+ appendStringInfoString(str, "PREPARE TRANSACTION ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_COMMIT_PREPARED:
+ appendStringInfoString(str, "COMMIT PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_ROLLBACK_PREPARED:
+ appendStringInfoString(str, "ROLLBACK PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
+{
+ ListCell *lc;
+
+ switch (variable_set_stmt->kind)
+ {
+ case VAR_SET_VALUE: /* SET var = value */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO ");
+ deparseVarList(str, variable_set_stmt->args);
+ break;
+ case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO DEFAULT");
+ break;
+ case VAR_SET_CURRENT: /* SET var FROM CURRENT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " FROM CURRENT");
+ break;
+ case VAR_SET_MULTI: /* special case for SET TRANSACTION ... */
+ Assert(variable_set_stmt->name != NULL);
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
+ {
+ appendStringInfoString(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION SNAPSHOT ");
+ deparseStringLiteral(str, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case VAR_RESET: /* RESET var */
+ appendStringInfoString(str, "RESET ");
+ deparseVarName(str, variable_set_stmt->name);
+ break;
+ case VAR_RESET_ALL: /* RESET ALL */
+ appendStringInfoString(str, "RESET ALL");
+ break;
+ }
+}
+
+static void deparseDropdbStmt(StringInfo str, DropdbStmt *dropdb_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "DROP DATABASE ");
+ if (dropdb_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, quote_identifier(dropdb_stmt->dbname));
+ appendStringInfoChar(str, ' ');
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ if (vacuum_stmt->is_vacuumcmd)
+ appendStringInfoString(str, "VACUUM ");
+ else
+ appendStringInfoString(str, "ANALYZE ");
+
+ if (list_length(vacuum_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, vacuum_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(str, def_elem->defname);
+ if (def_elem->arg != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ else
+ Assert(false);
+ }
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ foreach(lc, vacuum_stmt->rels)
+ {
+ Assert(IsA(lfirst(lc), VacuumRelation));
+ VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
+
+ deparseRangeVar(str, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(rel->va_cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc2, rel->va_cols)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc2))));
+ if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLoadStmt(StringInfo str, LoadStmt *load_stmt)
+{
+ appendStringInfoString(str, "LOAD ");
+ deparseStringLiteral(str, load_stmt->filename);
+}
+
+static void deparseLockStmt(StringInfo str, LockStmt *lock_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "LOCK TABLE ");
+
+ deparseRelationExprList(str, lock_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (lock_stmt->mode != AccessExclusiveLock)
+ {
+ appendStringInfoString(str, "IN ");
+ switch (lock_stmt->mode)
+ {
+ case AccessShareLock:
+ appendStringInfoString(str, "ACCESS SHARE ");
+ break;
+ case RowShareLock:
+ appendStringInfoString(str, "ROW SHARE ");
+ break;
+ case RowExclusiveLock:
+ appendStringInfoString(str, "ROW EXCLUSIVE ");
+ break;
+ case ShareUpdateExclusiveLock:
+ appendStringInfoString(str, "SHARE UPDATE EXCLUSIVE ");
+ break;
+ case ShareLock:
+ appendStringInfoString(str, "SHARE ");
+ break;
+ case ShareRowExclusiveLock:
+ appendStringInfoString(str, "SHARE ROW EXCLUSIVE ");
+ break;
+ case ExclusiveLock:
+ appendStringInfoString(str, "EXCLUSIVE ");
+ break;
+ case AccessExclusiveLock:
+ appendStringInfoString(str, "ACCESS EXCLUSIVE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+ appendStringInfoString(str, "MODE ");
+ }
+
+ if (lock_stmt->nowait)
+ appendStringInfoString(str, "NOWAIT ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraintsSetStmt(StringInfo str, ConstraintsSetStmt *constraints_set_stmt)
+{
+ appendStringInfoString(str, "SET CONSTRAINTS ");
+
+ if (list_length(constraints_set_stmt->constraints) > 0)
+ {
+ deparseQualifiedNameList(str, constraints_set_stmt->constraints);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ if (constraints_set_stmt->deferred)
+ appendStringInfoString(str, "DEFERRED");
+ else
+ appendStringInfoString(str, "IMMEDIATE");
+}
+
+static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ appendStringInfoString(str, "EXPLAIN ");
+
+ if (list_length(explain_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+
+ foreach(lc, explain_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ if (def_elem->arg != NULL && IsA(def_elem->arg, String))
+ {
+ appendStringInfoChar(str, ' ');
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (def_elem->arg != NULL && (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float)))
+ {
+ appendStringInfoChar(str, ' ');
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseExplainableStmt(str, explain_stmt->query);
+}
+
+static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "COPY ");
+
+ if (copy_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(copy_stmt->attlist) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, copy_stmt->attlist);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (copy_stmt->query != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, copy_stmt->query);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "FROM ");
+ else
+ appendStringInfoString(str, "TO ");
+
+ if (copy_stmt->is_program)
+ appendStringInfoString(str, "PROGRAM ");
+
+ if (copy_stmt->filename != NULL)
+ {
+ deparseStringLiteral(str, copy_stmt->filename);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "STDIN ");
+ else
+ appendStringInfoString(str, "STDOUT ");
+ }
+
+ if (list_length(copy_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "WITH (");
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "format") == 0)
+ {
+ appendStringInfoString(str, "FORMAT ");
+
+ char *format = strVal(def_elem->arg);
+ if (strcmp(format, "binary") == 0)
+ appendStringInfoString(str, "BINARY");
+ else if (strcmp(format, "csv") == 0)
+ appendStringInfoString(str, "CSV");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "freeze") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
+ {
+ appendStringInfoString(str, "FREEZE");
+ if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
+ appendStringInfoString(str, " 1");
+ }
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
+ {
+ appendStringInfoString(str, "DELIMITER ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "null") == 0)
+ {
+ appendStringInfoString(str, "NULL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "header") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
+ {
+ appendStringInfoString(str, "HEADER");
+ if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
+ appendStringInfoString(str, " 1");
+ }
+ else if (strcmp(def_elem->defname, "quote") == 0)
+ {
+ appendStringInfoString(str, "QUOTE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "escape") == 0)
+ {
+ appendStringInfoString(str, "ESCAPE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
+ {
+ appendStringInfoString(str, "FORCE_QUOTE ");
+ if (IsA(def_elem->arg, A_Star))
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NOT_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "force_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "encoding") == 0)
+ {
+ appendStringInfoString(str, "ENCODING ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL)
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ {
+ // Nothing
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ {
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAStar(str, castNode(A_Star, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoChar(str, '(');
+ foreach(lc2, l)
+ {
+ deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
+ if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ }
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseWhereClause(str, copy_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDoStmt(StringInfo str, DoStmt *do_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DO ");
+
+ foreach (lc, do_stmt->args)
+ {
+ DefElem *defel = castNode(DefElem, lfirst(lc));
+ if (strcmp(defel->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(defel->arg)));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defel->defname, "as") == 0)
+ {
+ char *strval = strVal(defel->arg);
+ const char *delim = "$$";
+ if (strstr(strval, "$$") != NULL)
+ delim = "$outer$";
+ appendStringInfoString(str, delim);
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, delim);
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDiscardStmt(StringInfo str, DiscardStmt *discard_stmt)
+{
+ appendStringInfoString(str, "DISCARD ");
+ switch (discard_stmt->target)
+ {
+ case DISCARD_ALL:
+ appendStringInfoString(str, "ALL");
+ break;
+ case DISCARD_PLANS:
+ appendStringInfoString(str, "PLANS");
+ break;
+ case DISCARD_SEQUENCES:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case DISCARD_TEMP:
+ appendStringInfoString(str, "TEMP");
+ break;
+ }
+}
+
+static void deparseDefineStmt(StringInfo str, DefineStmt *define_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (define_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ default:
+ // This shouldn't happen
+ Assert(false);
+ break;
+ }
+
+ if (define_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseFuncName(str, define_stmt->defnames);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAnyOperator(str, define_stmt->defnames);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_COLLATION:
+ deparseAnyName(str, define_stmt->defnames);
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
+ {
+ deparseAggrArgs(str, define_stmt->args);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (define_stmt->kind == OBJECT_COLLATION &&
+ list_length(define_stmt->definition) == 1 &&
+ strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
+ }
+ else if (list_length(define_stmt->definition) > 0)
+ {
+ deparseDefinition(str, define_stmt->definition);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCompositeTypeStmt(StringInfo str, CompositeTypeStmt *composite_type_stmt)
+{
+ ListCell *lc;
+ RangeVar *typevar;
+
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseRangeVar(str, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
+
+ appendStringInfoString(str, " AS (");
+ foreach(lc, composite_type_stmt->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateEnumStmt(StringInfo str, CreateEnumStmt *create_enum_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE TYPE ");
+
+ deparseAnyName(str, create_enum_stmt->typeName);
+ appendStringInfoString(str, " AS ENUM (");
+ foreach(lc, create_enum_stmt->vals)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateRangeStmt(StringInfo str, CreateRangeStmt *create_range_stmt)
+{
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseAnyName(str, create_range_stmt->typeName);
+ appendStringInfoString(str, " AS RANGE ");
+ deparseDefinition(str, create_range_stmt->params);
+}
+
+static void deparseAlterEnumStmt(StringInfo str, AlterEnumStmt *alter_enum_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_enum_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->oldVal == NULL)
+ {
+ appendStringInfoString(str, "ADD VALUE ");
+ if (alter_enum_stmt->skipIfNewValExists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->newValNeighbor)
+ {
+ if (alter_enum_stmt->newValIsAfter)
+ appendStringInfoString(str, "AFTER ");
+ else
+ appendStringInfoString(str, "BEFORE ");
+ deparseStringLiteral(str, alter_enum_stmt->newValNeighbor);
+ }
+ }
+ else
+ {
+ appendStringInfoString(str, "RENAME VALUE ");
+ deparseStringLiteral(str, alter_enum_stmt->oldVal);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionStmt(StringInfo str, AlterExtensionStmt *alter_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_stmt->extname);
+ appendStringInfoString(str, " UPDATE ");
+ foreach (lc, alter_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionContentsStmt(StringInfo str, AlterExtensionContentsStmt *alter_extension_contents_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_contents_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_extension_contents_stmt->action == 1)
+ appendStringInfoString(str, "ADD ");
+ else if (alter_extension_contents_stmt->action == -1)
+ appendStringInfoString(str, "DROP ");
+ else
+ Assert(false);
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ // No other object types are supported here in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ // any_name
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_TABLE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ deparseAnyName(str, castNode(List, alter_extension_contents_stmt->object));
+ break;
+ // name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_LANGUAGE:
+ case OBJECT_SCHEMA:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ deparseColId(str, strVal(alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ deparseTypeName(str, castNode(TypeName, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
+{
+ ListCell *lc;
+
+ if (access_priv->priv_name != NULL)
+ {
+ if (strcmp(access_priv->priv_name, "select") == 0)
+ appendStringInfoString(str, "select");
+ else if (strcmp(access_priv->priv_name, "references") == 0)
+ appendStringInfoString(str, "references");
+ else if (strcmp(access_priv->priv_name, "create") == 0)
+ appendStringInfoString(str, "create");
+ else
+ appendStringInfoString(str, quote_identifier(access_priv->priv_name));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(access_priv->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, access_priv->cols);
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
+{
+ ListCell *lc;
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "GRANT OPTION FOR ");
+
+ if (list_length(grant_stmt->privileges) > 0)
+ {
+ foreach(lc, grant_stmt->privileges)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ deparsePrivilegeTarget(str, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ foreach(lc, grant_stmt->grantees)
+ {
+ deparseRoleSpec(str, castNode(RoleSpec, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "WITH GRANT OPTION ");
+
+ deparseOptDropBehavior(str, grant_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
+{
+ ListCell *lc;
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ foreach(lc, grant_role_stmt->granted_roles)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ deparseRoleList(str, grant_role_stmt->grantee_roles);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_role_stmt->admin_opt)
+ appendStringInfoString(str, "WITH ADMIN OPTION ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropRoleStmt(StringInfo str, DropRoleStmt *drop_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DROP ROLE ");
+
+ if (drop_role_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRoleList(str, drop_role_stmt->roles);
+}
+
+static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (index_stmt->unique)
+ appendStringInfoString(str, "UNIQUE ");
+
+ appendStringInfoString(str, "INDEX ");
+
+ if (index_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (index_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (index_stmt->idxname != NULL)
+ {
+ appendStringInfoString(str, index_stmt->idxname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (index_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(index_stmt->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, index_stmt->indexParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+
+ if (list_length(index_stmt->indexIncludingParams) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ foreach (lc, index_stmt->indexIncludingParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, index_stmt->options);
+
+ if (index_stmt->tableSpace != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(index_stmt->tableSpace));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, index_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterOpFamilyStmt(StringInfo str, AlterOpFamilyStmt *alter_op_family_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR FAMILY ");
+ deparseAnyName(str, alter_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(alter_op_family_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_op_family_stmt->isDrop)
+ appendStringInfoString(str, "DROP ");
+ else
+ appendStringInfoString(str, "ADD ");
+
+ deparseOpclassItemList(str, alter_op_family_stmt->items);
+}
+
+static void deparsePrepareStmt(StringInfo str, PrepareStmt *prepare_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "PREPARE ");
+ deparseColId(str, prepare_stmt->name);
+ if (list_length(prepare_stmt->argtypes) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, prepare_stmt->argtypes);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoString(str, " AS ");
+ deparsePreparableStmt(str, prepare_stmt->query);
+}
+
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "EXECUTE ");
+ appendStringInfoString(str, quote_identifier(execute_stmt->name));
+ if (list_length(execute_stmt->params) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, execute_stmt->params);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseDeallocateStmt(StringInfo str, DeallocateStmt *deallocate_stmt)
+{
+ appendStringInfoString(str, "DEALLOCATE ");
+ if (deallocate_stmt->name != NULL)
+ appendStringInfoString(str, quote_identifier(deallocate_stmt->name));
+ else
+ appendStringInfoString(str, "ALL");
+}
+
+// "AlterOptRoleElem" in gram.y
+static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "password") == 0)
+ {
+ appendStringInfoString(str, "PASSWORD ");
+ if (def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NULL");
+ }
+ else if (IsA(def_elem->arg, ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "connectionlimit") == 0)
+ {
+ appendStringInfo(str, "CONNECTION LIMIT %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validUntil") == 0)
+ {
+ appendStringInfoString(str, "VALID UNTIL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "SUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOSUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOCREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "REPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOREPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOCREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "LOGIN");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOLOGIN");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "BYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOBYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "INHERIT");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOINHERIT");
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "CreateOptRoleElem" in gram.y
+static void deparseCreateRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "sysid") == 0)
+ {
+ appendStringInfo(str, "SYSID %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "adminmembers") == 0)
+ {
+ appendStringInfoString(str, "ADMIN ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "addroleto") == 0)
+ {
+ appendStringInfoString(str, "IN ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ deparseAlterRoleElem(str, def_elem);
+ }
+}
+
+static void deparseCreatePLangStmt(StringInfo str, CreatePLangStmt *create_p_lang_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+
+ if (create_p_lang_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ if (create_p_lang_stmt->pltrusted)
+ appendStringInfoString(str, "TRUSTED ");
+
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, create_p_lang_stmt->plname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_p_lang_stmt->plhandler);
+ appendStringInfoChar(str, ' ');
+
+ if (create_p_lang_stmt->plinline)
+ {
+ appendStringInfoString(str, "INLINE ");
+ deparseHandlerName(str, create_p_lang_stmt->plinline);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_p_lang_stmt->plvalidator)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, create_p_lang_stmt->plvalidator);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateRoleStmt(StringInfo str, CreateRoleStmt *create_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ switch (create_role_stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case ROLESTMT_USER:
+ appendStringInfoString(str, "USER ");
+ break;
+ case ROLESTMT_GROUP:
+ appendStringInfoString(str, "GROUP ");
+ break;
+ }
+
+ appendStringInfoString(str, quote_identifier(create_role_stmt->role));
+ appendStringInfoChar(str, ' ');
+
+ if (create_role_stmt->options != NULL)
+ {
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, create_role_stmt->options)
+ {
+ deparseCreateRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleStmt(StringInfo str, AlterRoleStmt *alter_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "GROUP ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_stmt->action == 1)
+ {
+ appendStringInfoString(str, "ADD USER ");
+ }
+ else if (alter_role_stmt->action == -1)
+ {
+ appendStringInfoString(str, "DROP USER ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseRoleList(str, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, alter_role_stmt->options)
+ {
+ deparseAlterRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeclareCursorStmt(StringInfo str, DeclareCursorStmt *declare_cursor_stmt)
+{
+ appendStringInfoString(str, "DECLARE ");
+ appendStringInfoString(str, quote_identifier(declare_cursor_stmt->portalname));
+ appendStringInfoChar(str, ' ');
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
+ appendStringInfoString(str, "BINARY ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
+ appendStringInfoString(str, "SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
+ appendStringInfoString(str, "NO SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
+ appendStringInfoString(str, "INSENSITIVE ");
+
+ appendStringInfoString(str, "CURSOR ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
+ appendStringInfoString(str, "WITH HOLD ");
+
+ appendStringInfoString(str, "FOR ");
+
+ deparseSelectStmt(str, castNode(SelectStmt, declare_cursor_stmt->query));
+}
+
+static void deparseFetchStmt(StringInfo str, FetchStmt *fetch_stmt)
+{
+ if (fetch_stmt->ismove)
+ appendStringInfoString(str, "MOVE ");
+ else
+ appendStringInfoString(str, "FETCH ");
+
+ switch (fetch_stmt->direction)
+ {
+ case FETCH_FORWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ // Default
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "FORWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_BACKWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "PRIOR ");
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "BACKWARD ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "BACKWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_ABSOLUTE:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "FIRST ");
+ }
+ else if (fetch_stmt->howMany == -1)
+ {
+ appendStringInfoString(str, "LAST ");
+ }
+ else
+ {
+ appendStringInfo(str, "ABSOLUTE %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_RELATIVE:
+ appendStringInfo(str, "RELATIVE %ld ", fetch_stmt->howMany);
+ }
+
+ appendStringInfoString(str, fetch_stmt->portalname);
+}
+
+static void deparseAlterDefaultPrivilegesStmt(StringInfo str, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER DEFAULT PRIVILEGES ");
+
+ foreach (lc, alter_default_privileges_stmt->options)
+ {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp(defelem->defname, "schemas") == 0)
+ {
+ appendStringInfoString(str, "IN SCHEMA ");
+ deparseNameList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defelem->defname, "roles") == 0)
+ {
+ appendStringInfoString(str, "FOR ROLE ");
+ deparseRoleList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ // No other DefElems are supported
+ Assert(false);
+ }
+ }
+
+ deparseGrantStmt(str, alter_default_privileges_stmt->action);
+}
+
+static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
+{
+ appendStringInfoString(str, "REINDEX ");
+
+ if (reindex_stmt->options & REINDEXOPT_VERBOSE)
+ appendStringInfoString(str, "(VERBOSE) ");
+
+ switch (reindex_stmt->kind)
+ {
+ case REINDEX_OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case REINDEX_OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case REINDEX_OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case REINDEX_OBJECT_SYSTEM:
+ appendStringInfoString(str, "SYSTEM ");
+ break;
+ case REINDEX_OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ }
+
+ if (reindex_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (reindex_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (reindex_stmt->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(reindex_stmt->name));
+ }
+}
+
+static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (rule_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "RULE ");
+ appendStringInfoString(str, quote_identifier(rule_stmt->rulename));
+ appendStringInfoString(str, " AS ON ");
+
+ switch (rule_stmt->event)
+ {
+ case CMD_UNKNOWN:
+ case CMD_UTILITY:
+ case CMD_NOTHING:
+ // Not supported here
+ Assert(false);
+ break;
+ case CMD_SELECT:
+ appendStringInfoString(str, "SELECT ");
+ break;
+ case CMD_UPDATE:
+ appendStringInfoString(str, "UPDATE ");
+ break;
+ case CMD_INSERT:
+ appendStringInfoString(str, "INSERT ");
+ break;
+ case CMD_DELETE:
+ appendStringInfoString(str, "DELETE ");
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ deparseRangeVar(str, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseWhereClause(str, rule_stmt->whereClause);
+
+ appendStringInfoString(str, "DO ");
+
+ if (rule_stmt->instead)
+ appendStringInfoString(str, "INSTEAD ");
+
+ if (list_length(rule_stmt->actions) == 0)
+ {
+ appendStringInfoString(str, "NOTHING");
+ }
+ else if (list_length(rule_stmt->actions) == 1)
+ {
+ deparseRuleActionStmt(str, linitial(rule_stmt->actions));
+ }
+ else
+ {
+ appendStringInfoChar(str, '(');
+ foreach (lc, rule_stmt->actions)
+ {
+ deparseRuleActionStmt(str, lfirst(lc));
+ if (lnext(lc))
+ appendStringInfoString(str, "; ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseNotifyStmt(StringInfo str, NotifyStmt *notify_stmt)
+{
+ appendStringInfoString(str, "NOTIFY ");
+ appendStringInfoString(str, quote_identifier(notify_stmt->conditionname));
+
+ if (notify_stmt->payload != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseStringLiteral(str, notify_stmt->payload);
+ }
+}
+
+static void deparseListenStmt(StringInfo str, ListenStmt *listen_stmt)
+{
+ appendStringInfoString(str, "LISTEN ");
+ appendStringInfoString(str, quote_identifier(listen_stmt->conditionname));
+}
+
+static void deparseUnlistenStmt(StringInfo str, UnlistenStmt *unlisten_stmt)
+{
+ appendStringInfoString(str, "UNLISTEN ");
+ if (unlisten_stmt->conditionname == NULL)
+ appendStringInfoString(str, "*");
+ else
+ appendStringInfoString(str, quote_identifier(unlisten_stmt->conditionname));
+}
+
+static void deparseCreateSeqStmt(StringInfo str, CreateSeqStmt *create_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_seq_stmt->sequence->relpersistence);
+
+ appendStringInfoString(str, "SEQUENCE ");
+
+ if (create_seq_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptSeqOptList(str, create_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFunctionStmt(StringInfo str, AlterFunctionStmt *alter_function_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_function_stmt->objtype)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ deparseFunctionWithArgtypes(str, alter_function_stmt->func);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, alter_function_stmt->actions)
+ {
+ deparseCommonFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseTruncateStmt(StringInfo str, TruncateStmt *truncate_stmt)
+{
+ appendStringInfoString(str, "TRUNCATE ");
+
+ deparseRelationExprList(str, truncate_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (truncate_stmt->restart_seqs)
+ appendStringInfoString(str, "RESTART IDENTITY ");
+
+ deparseOptDropBehavior(str, truncate_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateEventTrigStmt(StringInfo str, CreateEventTrigStmt *create_event_trig_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "CREATE EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "ON ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->eventname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_event_trig_stmt->whenclause)
+ {
+ appendStringInfoString(str, "WHEN ");
+
+ foreach (lc, create_event_trig_stmt->whenclause)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " IN (");
+ foreach (lc2, l)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc2)));
+ if (lnext(lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ if (lnext(lc))
+ appendStringInfoString(str, " AND ");
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_event_trig_stmt->funcname);
+ appendStringInfoString(str, "()");
+}
+
+static void deparseAlterEventTrigStmt(StringInfo str, AlterEventTrigStmt *alter_event_trig_stmt)
+{
+ appendStringInfoString(str, "ALTER EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(alter_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_event_trig_stmt->tgenabled)
+ {
+ case TRIGGER_FIRES_ON_ORIGIN:
+ appendStringInfoString(str, "ENABLE");
+ break;
+ case TRIGGER_FIRES_ON_REPLICA:
+ appendStringInfoString(str, "ENABLE REPLICA");
+ break;
+ case TRIGGER_FIRES_ALWAYS:
+ appendStringInfoString(str, "ENABLE ALWAYS");
+ break;
+ case TRIGGER_DISABLED:
+ appendStringInfoString(str, "DISABLE");
+ break;
+ }
+}
+
+static void deparseRefreshMatViewStmt(StringInfo str, RefreshMatViewStmt *refresh_mat_view_stmt)
+{
+ appendStringInfoString(str, "REFRESH MATERIALIZED VIEW ");
+
+ if (refresh_mat_view_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ deparseRangeVar(str, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (refresh_mat_view_stmt->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt)
+{
+ switch (replica_identity_stmt->identity_type)
+ {
+ case REPLICA_IDENTITY_NOTHING:
+ appendStringInfoString(str, "NOTHING ");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ appendStringInfoString(str, "FULL ");
+ break;
+ case REPLICA_IDENTITY_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ Assert(replica_identity_stmt->name != NULL);
+ appendStringInfoString(str, "USING INDEX ");
+ appendStringInfoString(str, quote_identifier(replica_identity_stmt->name));
+ break;
+ }
+}
+
+static void deparseCreatePolicyStmt(StringInfo str, CreatePolicyStmt *create_policy_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE POLICY ");
+ deparseColId(str, create_policy_stmt->policy_name);
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (!create_policy_stmt->permissive)
+ appendStringInfoString(str, "AS RESTRICTIVE ");
+
+ if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
+ Assert(true); // Default
+ else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
+ appendStringInfoString(str, "FOR SELECT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
+ appendStringInfoString(str, "FOR INSERT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
+ appendStringInfoString(str, "FOR UPDATE ");
+ else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
+ appendStringInfoString(str, "FOR DELETE ");
+ else
+ Assert(false);
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, create_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ if (create_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, create_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (create_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, create_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseAlterPolicyStmt(StringInfo str, AlterPolicyStmt *alter_policy_stmt)
+{
+ appendStringInfoString(str, "ALTER POLICY ");
+ appendStringInfoString(str, quote_identifier(alter_policy_stmt->policy_name));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_policy_stmt->roles) > 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, alter_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, alter_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (alter_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, alter_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *create_table_space_stmt)
+{
+ appendStringInfoString(str, "CREATE TABLESPACE ");
+ deparseColId(str, create_table_space_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_space_stmt->owner != NULL)
+ {
+ appendStringInfoString(str, "OWNER ");
+ deparseRoleSpec(str, create_table_space_stmt->owner);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "LOCATION ");
+ deparseStringLiteral(str, create_table_space_stmt->location);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptWith(str, create_table_space_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTransformStmt(StringInfo str, CreateTransformStmt *create_transform_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_transform_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "TRANSFORM FOR ");
+ deparseTypeName(str, create_transform_stmt->type_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(create_transform_stmt->lang));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoChar(str, '(');
+
+ if (create_transform_stmt->fromsql)
+ {
+ appendStringInfoString(str, "FROM SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->fromsql);
+ }
+
+ if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
+ appendStringInfoString(str, ", ");
+
+ if (create_transform_stmt->tosql)
+ {
+ appendStringInfoString(str, "TO SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->tosql);
+ }
+
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
+{
+ appendStringInfoString(str, "CREATE ACCESS METHOD ");
+ appendStringInfoString(str, quote_identifier(create_am_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TYPE ");
+ switch (create_am_stmt->amtype)
+ {
+ case AMTYPE_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case AMTYPE_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ }
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_am_stmt->handler_name);
+}
+
+static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_publication_stmt->tables) > 0)
+ {
+ appendStringInfoString(str, "FOR TABLE ");
+ deparseRelationExprList(str, create_publication_stmt->tables);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_publication_stmt->for_all_tables)
+ {
+ appendStringInfoString(str, "FOR ALL TABLES ");
+ }
+
+ deparseOptDefinition(str, create_publication_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *alter_publication_stmt)
+{
+ appendStringInfoString(str, "ALTER PUBLICATION ");
+ deparseColId(str, alter_publication_stmt->pubname);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_publication_stmt->tables) > 0)
+ {
+ switch (alter_publication_stmt->tableAction)
+ {
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET TABLE ");
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD TABLE ");
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP TABLE ");
+ break;
+ case DEFELEM_UNSPEC:
+ Assert(false);
+ break;
+ }
+
+ deparseRelationExprList(str, alter_publication_stmt->tables);
+ }
+ else if (list_length(alter_publication_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_publication_stmt->options);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+static void deparseAlterSeqStmt(StringInfo str, AlterSeqStmt *alter_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SEQUENCE ");
+
+ if (alter_seq_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseSeqOptList(str, alter_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSystemStmt(StringInfo str, AlterSystemStmt *alter_system_stmt)
+{
+ appendStringInfoString(str, "ALTER SYSTEM ");
+ deparseVariableSetStmt(str, alter_system_stmt->setstmt);
+}
+
+static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "COMMENT ON ");
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ deparseAnyName(str, castNode(List, comment_stmt->object));
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(strVal(comment_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ deparseTypeName(str, castNode(TypeName, comment_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON DOMAIN ");
+ deparseTypeName(str, linitial(l));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(lsecond(l))));
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, comment_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseValue(str, (Value *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (comment_stmt->comment != NULL)
+ deparseStringLiteral(str, comment_stmt->comment);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE STATISTICS ");
+
+ if (create_stats_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseAnyName(str, create_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_stats_stmt->stat_types) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, create_stats_stmt->stat_types);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseExprList(str, create_stats_stmt->exprs);
+
+ appendStringInfoString(str, " FROM ");
+ deparseFromList(str, create_stats_stmt->relations);
+}
+
+static void deparseAlterCollationStmt(StringInfo str, AlterCollationStmt *alter_collation_stmt)
+{
+ appendStringInfoString(str, "ALTER COLLATION ");
+ deparseAnyName(str, alter_collation_stmt->collname);
+ appendStringInfoString(str, " REFRESH VERSION");
+}
+
+static void deparseAlterDatabaseStmt(StringInfo str, AlterDatabaseStmt *alter_database_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, alter_database_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterDatabaseSetStmt(StringInfo str, AlterDatabaseSetStmt *alter_database_set_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_set_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseVariableSetStmt(str, alter_database_set_stmt->setstmt);
+}
+
+static void deparseAlterTSDictionaryStmt(StringInfo str, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
+{
+ appendStringInfoString(str, "ALTER TEXT SEARCH DICTIONARY ");
+
+ deparseAnyName(str, alter_ts_dictionary_stmt->dictname);
+ appendStringInfoChar(str, ' ');
+
+ deparseDefinition(str, alter_ts_dictionary_stmt->options);
+}
+
+static void deparseAlterTSConfigurationStmt(StringInfo str, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, alter_ts_configuration_stmt->cfgname);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_ts_configuration_stmt->kind)
+ {
+ case ALTER_TSCONFIG_ADD_MAPPING:
+ appendStringInfoString(str, "ADD MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT:
+ appendStringInfoString(str, "ALTER MAPPING REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_DROP_MAPPING:
+ appendStringInfoString(str, "DROP MAPPING ");
+ if (alter_ts_configuration_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, "FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ break;
+ }
+}
+
+static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_show_stmt)
+{
+ appendStringInfoString(str, "SHOW ");
+
+ if (strcmp(variable_show_stmt->name, "timezone") == 0)
+ appendStringInfoString(str, "TIME ZONE");
+ else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
+ appendStringInfoString(str, "TRANSACTION ISOLATION LEVEL");
+ else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
+ appendStringInfoString(str, "SESSION AUTHORIZATION");
+ else if (strcmp(variable_show_stmt->name, "all") == 0)
+ appendStringInfoString(str, "SESSION ALL");
+ else
+ appendStringInfoString(str, variable_show_stmt->name);
+}
+
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
+{
+ deparseRangeVar(str, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
+
+ appendStringInfoString(str, " TABLESAMPLE ");
+
+ deparseFuncName(str, range_table_sample->method);
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, range_table_sample->args);
+ appendStringInfoString(str, ") ");
+
+ if (range_table_sample->repeatable != NULL)
+ {
+ appendStringInfoString(str, "REPEATABLE (");
+ deparseExpr(str, range_table_sample->repeatable);
+ appendStringInfoString(str, ") ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateSubscriptionStmt(StringInfo str, CreateSubscriptionStmt *create_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(create_subscription_stmt->subname));
+
+ appendStringInfoString(str, " CONNECTION ");
+ if (create_subscription_stmt->conninfo != NULL)
+ deparseStringLiteral(str, create_subscription_stmt->conninfo);
+ else
+ appendStringInfoString(str, "''");
+
+ appendStringInfoString(str, " PUBLICATION ");
+
+ foreach(lc, create_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDefinition(str, create_subscription_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *alter_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(alter_subscription_stmt->subname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_subscription_stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ appendStringInfoString(str, "CONNECTION ");
+ deparseStringLiteral(str, alter_subscription_stmt->conninfo);
+ appendStringInfoChar(str, ' ');
+ break;
+ case ALTER_SUBSCRIPTION_REFRESH:
+ appendStringInfoString(str, "REFRESH PUBLICATION ");
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_PUBLICATION:
+ appendStringInfoString(str, "SET PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ENABLED:
+ Assert(list_length(alter_subscription_stmt->options) == 1);
+ DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
+ Assert(strcmp(defelem->defname, "enabled") == 0);
+ if (intVal(defelem->arg) == 1)
+ {
+ appendStringInfoString(str, " ENABLE ");
+ }
+ else if (intVal(defelem->arg) == 0)
+ {
+ appendStringInfoString(str, " DISABLE ");
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropSubscriptionStmt(StringInfo str, DropSubscriptionStmt *drop_subscription_stmt)
+{
+ appendStringInfoString(str, "DROP SUBSCRIPTION ");
+
+ if (drop_subscription_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_subscription_stmt->subname);
+}
+
+static void deparseCallStmt(StringInfo str, CallStmt *call_stmt)
+{
+ appendStringInfoString(str, "CALL ");
+ deparseFuncCall(str, call_stmt->funccall);
+}
+
+static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_owner_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnly(str, (Value *) alter_owner_stmt->object);
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ default:
+ Assert(false);
+ }
+
+ appendStringInfoString(str, " OWNER TO ");
+ deparseRoleSpec(str, alter_owner_stmt->newowner);
+}
+
+// "operator_def_list" in gram.y
+static void deparseOperatorDefList(StringInfo str, List *defs)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, defs)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " = ");
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, true);
+ else
+ appendStringInfoString(str, "NONE");
+
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterOperatorStmt(StringInfo str, AlterOperatorStmt *alter_operator_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR ");
+ deparseOperatorWithArgtypes(str, alter_operator_stmt->opername);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_operator_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseDropOwnedStmt(StringInfo str, DropOwnedStmt *drop_owned_stmt)
+{
+ appendStringInfoString(str, "DROP OWNED BY ");
+ deparseRoleList(str, drop_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ deparseOptDropBehavior(str, drop_owned_stmt->behavior);
+ removeTrailingSpace(str);
+}
+
+static void deparseReassignOwnedStmt(StringInfo str, ReassignOwnedStmt *reassigned_owned_stmt)
+{
+ appendStringInfoString(str, "REASSIGN OWNED BY ");
+
+ deparseRoleList(str, reassigned_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleSpec(str, reassigned_owned_stmt->newrole);
+}
+
+static void deparseClosePortalStmt(StringInfo str, ClosePortalStmt *close_portal_stmt)
+{
+ appendStringInfoString(str, "CLOSE ");
+ if (close_portal_stmt->portalname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(close_portal_stmt->portalname));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+}
+
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr)
+{
+ appendStringInfoString(str, "CURRENT OF ");
+ appendStringInfoString(str, quote_identifier(current_of_expr->cursor_name));
+}
+
+static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_stmt)
+{
+ ListCell *lc;
+ bool skip_events_or = true;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_trig_stmt->isconstraint)
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, "TRIGGER ");
+
+ appendStringInfoString(str, quote_identifier(create_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (create_trig_stmt->timing)
+ {
+ case TRIGGER_TYPE_BEFORE:
+ appendStringInfoString(str, "BEFORE ");
+ break;
+ case TRIGGER_TYPE_AFTER:
+ appendStringInfoString(str, "AFTER ");
+ break;
+ case TRIGGER_TYPE_INSTEAD:
+ appendStringInfoString(str, "INSTEAD OF ");
+ break;
+ default:
+ Assert(false);
+ }
+
+ if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
+ {
+ appendStringInfoString(str, "INSERT ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "DELETE ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "UPDATE ");
+ if (list_length(create_trig_stmt->columns) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseColumnList(str, create_trig_stmt->columns);
+ appendStringInfoChar(str, ' ');
+ }
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "TRUNCATE ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_trig_stmt->transitionRels != NULL)
+ {
+ appendStringInfoString(str, "REFERENCING ");
+ foreach(lc, create_trig_stmt->transitionRels)
+ {
+ deparseTriggerTransition(str, castNode(TriggerTransition, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ if (create_trig_stmt->constrrel != NULL)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseRangeVar(str, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_trig_stmt->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (create_trig_stmt->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (create_trig_stmt->row)
+ appendStringInfoString(str, "FOR EACH ROW ");
+
+ if (create_trig_stmt->whenClause)
+ {
+ appendStringInfoString(str, "WHEN (");
+ deparseExpr(str, create_trig_stmt->whenClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_trig_stmt->funcname);
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_trig_stmt->args)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition)
+{
+ if (trigger_transition->isNew)
+ appendStringInfoString(str, "NEW ");
+ else
+ appendStringInfoString(str, "OLD ");
+
+ if (trigger_transition->isTable)
+ appendStringInfoString(str, "TABLE ");
+ else
+ appendStringInfoString(str, "ROW ");
+
+ appendStringInfoString(str, quote_identifier(trigger_transition->name));
+}
+
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
+{
+ switch (xml_expr->op)
+ {
+ case IS_XMLCONCAT: /* XMLCONCAT(args) */
+ appendStringInfoString(str, "xmlconcat(");
+ deparseExprList(str, xml_expr->args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
+ appendStringInfoString(str, "xmlelement(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->named_args != NULL)
+ {
+ appendStringInfoString(str, ", xmlattributes(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoString(str, ")");
+ }
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExprList(str, xml_expr->args);
+ }
+ appendStringInfoString(str, ")");
+ break;
+ case IS_XMLFOREST: /* XMLFOREST(xml_attributes) */
+ appendStringInfoString(str, "xmlforest(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
+ Assert(list_length(xml_expr->args) == 2);
+ appendStringInfoString(str, "xmlparse(");
+ switch (xml_expr->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, linitial(xml_expr->args));
+ if (strcmp(strVal(&castNode(A_Const, castNode(TypeCast, lsecond(xml_expr->args))->arg)->val), "t") == 0)
+ appendStringInfoString(str, " PRESERVE WHITESPACE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPI: /* XMLPI(name [, args]) */
+ appendStringInfoString(str, "xmlpi(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, linitial(xml_expr->args));
+ }
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
+ appendStringInfoString(str, "xmlroot(");
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, ", version ");
+ if (nodeTag(&castNode(A_Const, lsecond(xml_expr->args))->val) == T_Null)
+ appendStringInfoString(str, "NO VALUE");
+ else
+ deparseExpr(str, lsecond(xml_expr->args));
+ if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
+ appendStringInfoString(str, ", STANDALONE YES");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
+ appendStringInfoString(str, ", STANDALONE NO");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
+ appendStringInfoString(str, ", STANDALONE NO VALUE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLSERIALIZE: /* XMLSERIALIZE(is_document, xmlval) */
+ // These are represented as XmlSerialize in raw parse trees
+ Assert(false);
+ break;
+ case IS_DOCUMENT: /* xmlval IS DOCUMENT */
+ Assert(list_length(xml_expr->args) == 1);
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, " IS DOCUMENT");
+ break;
+ }
+}
+
+static void deparseRangeTableFuncCol(StringInfo str, RangeTableFuncCol* range_table_func_col)
+{
+ appendStringInfoString(str, quote_identifier(range_table_func_col->colname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->for_ordinality)
+ {
+ appendStringInfoString(str, "FOR ORDINALITY ");
+ }
+ else
+ {
+ deparseTypeName(str, range_table_func_col->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->colexpr)
+ {
+ appendStringInfoString(str, "PATH ");
+ deparseExpr(str, range_table_func_col->colexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->coldefexpr)
+ {
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, range_table_func_col->coldefexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->is_not_null)
+ appendStringInfoString(str, "NOT NULL ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func)
+{
+ ListCell *lc;
+
+ if (range_table_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoString(str, "xmltable(");
+ if (range_table_func->namespaces)
+ {
+ appendStringInfoString(str, "xmlnamespaces(");
+ deparseXmlNamespaceList(str, range_table_func->namespaces);
+ appendStringInfoString(str, "), ");
+ }
+
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, range_table_func->rowexpr);
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, range_table_func->docexpr);
+
+ appendStringInfoString(str, " COLUMNS ");
+ foreach(lc, range_table_func->columns)
+ {
+ deparseRangeTableFuncCol(str, castNode(RangeTableFuncCol, lfirst(lc)));
+ if (lnext(lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, ") ");
+
+ if (range_table_func->alias)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_table_func->alias);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize)
+{
+ appendStringInfoString(str, "xmlserialize(");
+ switch (xml_serialize->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, xml_serialize->expr);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, xml_serialize->typeName);
+ appendStringInfoString(str, ")");
+}
+
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
+{
+ appendStringInfoString(str, "GROUPING(");
+ deparseExprList(str, grouping_func->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
+{
+ appendStringInfoString(str, "CLUSTER ");
+ if (cluster_stmt->options & CLUOPT_VERBOSE)
+ appendStringInfoString(str, "VERBOSE ");
+
+ if (cluster_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (cluster_stmt->indexname != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(cluster_stmt->indexname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ case T_Float:
+ deparseNumericOnly(str, value);
+ break;
+ case T_String:
+ if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
+ appendStringInfoString(str, quote_identifier(value->val.str));
+ } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
+ deparseStringLiteral(str, value->val.str);
+ } else {
+ appendStringInfoString(str, value->val.str);
+ }
+ break;
+ case T_BitString:
+ if (strlen(value->val.str) >= 1 && value->val.str[0] == 'x')
+ {
+ appendStringInfoChar(str, 'x');
+ deparseStringLiteral(str, value->val.str + 1);
+ }
+ else if (strlen(value->val.str) >= 1 && value->val.str[0] == 'b')
+ {
+ appendStringInfoChar(str, 'b');
+ deparseStringLiteral(str, value->val.str + 1);
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case T_Null:
+ appendStringInfoString(str, "NULL");
+ break;
+ default:
+ elog(ERROR, "deparse: unrecognized value node type: %d",
+ (int) nodeTag(value));
+ break;
+ }
+}
+
+// "PrepareableStmt" in gram.y
+static void deparsePreparableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "RuleActionStmt" in gram.y
+static void deparseRuleActionStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "ExplainableStmt" in gram.y
+static void deparseExplainableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_CreateTableAsStmt:
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "schema_stmt" in gram.y
+static void deparseSchemaStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "stmt" in gram.y
+static void deparseStmt(StringInfo str, Node *node)
+{
+ // Note the following grammar names are missing in the list, because they
+ // get mapped to other node types:
+ //
+ // - AlterForeignTableStmt (=> AlterTableStmt)
+ // - AlterGroupStmt (=> AlterRoleStmt)
+ // - AlterCompositeTypeStmt (=> AlterTableStmt)
+ // - AnalyzeStmt (=> VacuumStmt)
+ // - CreateGroupStmt (=> CreateRoleStmt)
+ // - CreateMatViewStmt (=> CreateTableAsStmt)
+ // - CreateUserStmt (=> CreateRoleStmt)
+ // - DropCastStmt (=> DropStmt)
+ // - DropOpClassStmt (=> DropStmt)
+ // - DropOpFamilyStmt (=> DropStmt)
+ // - DropPLangStmt (=> DropPLangStmt)
+ // - DropTransformStmt (=> DropStmt)
+ // - RemoveAggrStmt (=> DropStmt)
+ // - RemoveFuncStmt (=> DropStmt)
+ // - RemoveOperStmt (=> DropStmt)
+ // - RevokeStmt (=> GrantStmt)
+ // - RevokeRoleStmt (=> GrantRoleStmt)
+ // - VariableResetStmt (=> VariableSetStmt)
+ //
+ // And the following grammar names error out in the parser:
+ // - CreateAssertionStmt (not supported yet)
+ switch (nodeTag(node))
+ {
+ case T_AlterEventTrigStmt:
+ deparseAlterEventTrigStmt(str, castNode(AlterEventTrigStmt, node));
+ break;
+ case T_AlterCollationStmt:
+ deparseAlterCollationStmt(str, castNode(AlterCollationStmt, node));
+ break;
+ case T_AlterDatabaseStmt:
+ deparseAlterDatabaseStmt(str, castNode(AlterDatabaseStmt, node));
+ break;
+ case T_AlterDatabaseSetStmt:
+ deparseAlterDatabaseSetStmt(str, castNode(AlterDatabaseSetStmt, node));
+ break;
+ case T_AlterDefaultPrivilegesStmt:
+ deparseAlterDefaultPrivilegesStmt(str, castNode(AlterDefaultPrivilegesStmt, node));
+ break;
+ case T_AlterDomainStmt:
+ deparseAlterDomainStmt(str, castNode(AlterDomainStmt, node));
+ break;
+ case T_AlterEnumStmt:
+ deparseAlterEnumStmt(str, castNode(AlterEnumStmt, node));
+ break;
+ case T_AlterExtensionStmt:
+ deparseAlterExtensionStmt(str, castNode(AlterExtensionStmt, node));
+ break;
+ case T_AlterExtensionContentsStmt:
+ deparseAlterExtensionContentsStmt(str, castNode(AlterExtensionContentsStmt, node));
+ break;
+ case T_AlterFdwStmt:
+ deparseAlterFdwStmt(str, castNode(AlterFdwStmt, node));
+ break;
+ case T_AlterForeignServerStmt:
+ deparseAlterForeignServerStmt(str, castNode(AlterForeignServerStmt, node));
+ break;
+ case T_AlterFunctionStmt:
+ deparseAlterFunctionStmt(str, castNode(AlterFunctionStmt, node));
+ break;
+ case T_AlterObjectDependsStmt:
+ deparseAlterObjectDependsStmt(str, castNode(AlterObjectDependsStmt, node));
+ break;
+ case T_AlterObjectSchemaStmt:
+ deparseAlterObjectSchemaStmt(str, castNode(AlterObjectSchemaStmt, node));
+ break;
+ case T_AlterOwnerStmt:
+ deparseAlterOwnerStmt(str, castNode(AlterOwnerStmt, node));
+ break;
+ case T_AlterOperatorStmt:
+ deparseAlterOperatorStmt(str, castNode(AlterOperatorStmt, node));
+ break;
+ case T_AlterPolicyStmt:
+ deparseAlterPolicyStmt(str, castNode(AlterPolicyStmt, node));
+ break;
+ case T_AlterSeqStmt:
+ deparseAlterSeqStmt(str, castNode(AlterSeqStmt, node));
+ break;
+ case T_AlterSystemStmt:
+ deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
+ break;
+ case T_AlterTableStmt:
+ deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
+ break;
+ case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
+ deparseAlterTableSpaceOptionsStmt(str, castNode(AlterTableSpaceOptionsStmt, node));
+ break;
+ case T_AlterPublicationStmt:
+ deparseAlterPublicationStmt(str, castNode(AlterPublicationStmt, node));
+ break;
+ case T_AlterRoleSetStmt:
+ deparseAlterRoleSetStmt(str, castNode(AlterRoleSetStmt, node));
+ break;
+ case T_AlterRoleStmt:
+ deparseAlterRoleStmt(str, castNode(AlterRoleStmt, node));
+ break;
+ case T_AlterSubscriptionStmt:
+ deparseAlterSubscriptionStmt(str, castNode(AlterSubscriptionStmt, node));
+ break;
+ case T_AlterTSConfigurationStmt:
+ deparseAlterTSConfigurationStmt(str, castNode(AlterTSConfigurationStmt, node));
+ break;
+ case T_AlterTSDictionaryStmt:
+ deparseAlterTSDictionaryStmt(str, castNode(AlterTSDictionaryStmt, node));
+ break;
+ case T_AlterUserMappingStmt:
+ deparseAlterUserMappingStmt(str, castNode(AlterUserMappingStmt, node));
+ break;
+ case T_CallStmt:
+ deparseCallStmt(str, castNode(CallStmt, node));
+ break;
+ case T_CheckPointStmt:
+ deparseCheckPointStmt(str, castNode(CheckPointStmt, node));
+ break;
+ case T_ClosePortalStmt:
+ deparseClosePortalStmt(str, castNode(ClosePortalStmt, node));
+ break;
+ case T_ClusterStmt:
+ deparseClusterStmt(str, castNode(ClusterStmt, node));
+ break;
+ case T_CommentStmt:
+ deparseCommentStmt(str, castNode(CommentStmt, node));
+ break;
+ case T_ConstraintsSetStmt:
+ deparseConstraintsSetStmt(str, castNode(ConstraintsSetStmt, node));
+ break;
+ case T_CopyStmt:
+ deparseCopyStmt(str, castNode(CopyStmt, node));
+ break;
+ case T_CreateAmStmt:
+ deparseCreateAmStmt(str, castNode(CreateAmStmt, node));
+ break;
+ case T_CreateTableAsStmt: // "CreateAsStmt" in gram.y
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_CreateCastStmt:
+ deparseCreateCastStmt(str, castNode(CreateCastStmt, node));
+ break;
+ case T_CreateConversionStmt:
+ deparseCreateConversionStmt(str, castNode(CreateConversionStmt, node));
+ break;
+ case T_CreateDomainStmt:
+ deparseCreateDomainStmt(str, castNode(CreateDomainStmt, node));
+ break;
+ case T_CreateExtensionStmt:
+ deparseCreateExtensionStmt(str, castNode(CreateExtensionStmt, node));
+ break;
+ case T_CreateFdwStmt:
+ deparseCreateFdwStmt(str, castNode(CreateFdwStmt, node));
+ break;
+ case T_CreateForeignServerStmt:
+ deparseCreateForeignServerStmt(str, castNode(CreateForeignServerStmt, node));
+ break;
+ case T_CreateForeignTableStmt:
+ deparseCreateForeignTableStmt(str, castNode(CreateForeignTableStmt, node));
+ break;
+ case T_CreateFunctionStmt:
+ deparseCreateFunctionStmt(str, castNode(CreateFunctionStmt, node));
+ break;
+ case T_CreateOpClassStmt:
+ deparseCreateOpClassStmt(str, castNode(CreateOpClassStmt, node));
+ break;
+ case T_CreateOpFamilyStmt:
+ deparseCreateOpFamilyStmt(str, castNode(CreateOpFamilyStmt, node));
+ break;
+ case T_CreatePublicationStmt:
+ deparseCreatePublicationStmt(str, castNode(CreatePublicationStmt, node));
+ break;
+ case T_AlterOpFamilyStmt:
+ deparseAlterOpFamilyStmt(str, castNode(AlterOpFamilyStmt, node));
+ break;
+ case T_CreatePolicyStmt:
+ deparseCreatePolicyStmt(str, castNode(CreatePolicyStmt, node));
+ break;
+ case T_CreatePLangStmt:
+ deparseCreatePLangStmt(str, castNode(CreatePLangStmt, node));
+ break;
+ case T_CreateSchemaStmt:
+ deparseCreateSchemaStmt(str, castNode(CreateSchemaStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_CreateSubscriptionStmt:
+ deparseCreateSubscriptionStmt(str, castNode(CreateSubscriptionStmt, node));
+ break;
+ case T_CreateStatsStmt:
+ deparseCreateStatsStmt(str, castNode(CreateStatsStmt, node));
+ break;
+ case T_CreateTableSpaceStmt:
+ deparseCreateTableSpaceStmt(str, castNode(CreateTableSpaceStmt, node));
+ break;
+ case T_CreateTransformStmt:
+ deparseCreateTransformStmt(str, castNode(CreateTransformStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_CreateEventTrigStmt:
+ deparseCreateEventTrigStmt(str, castNode(CreateEventTrigStmt, node));
+ break;
+ case T_CreateRoleStmt:
+ deparseCreateRoleStmt(str, castNode(CreateRoleStmt, node));
+ break;
+ case T_CreateUserMappingStmt:
+ deparseCreateUserMappingStmt(str, castNode(CreateUserMappingStmt, node));
+ break;
+ case T_CreatedbStmt:
+ deparseCreatedbStmt(str, castNode(CreatedbStmt, node));
+ break;
+ case T_DeallocateStmt:
+ deparseDeallocateStmt(str, castNode(DeallocateStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_DefineStmt:
+ deparseDefineStmt(str, castNode(DefineStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DiscardStmt:
+ deparseDiscardStmt(str, castNode(DiscardStmt, node));
+ break;
+ case T_DoStmt:
+ deparseDoStmt(str, castNode(DoStmt, node));
+ break;
+ case T_DropOwnedStmt:
+ deparseDropOwnedStmt(str, castNode(DropOwnedStmt, node));
+ break;
+ case T_DropStmt:
+ deparseDropStmt(str, castNode(DropStmt, node));
+ break;
+ case T_DropSubscriptionStmt:
+ deparseDropSubscriptionStmt(str, castNode(DropSubscriptionStmt, node));
+ break;
+ case T_DropTableSpaceStmt:
+ deparseDropTableSpaceStmt(str, castNode(DropTableSpaceStmt, node));
+ break;
+ case T_DropRoleStmt:
+ deparseDropRoleStmt(str, castNode(DropRoleStmt, node));
+ break;
+ case T_DropUserMappingStmt:
+ deparseDropUserMappingStmt(str, castNode(DropUserMappingStmt, node));
+ break;
+ case T_DropdbStmt:
+ deparseDropdbStmt(str, castNode(DropdbStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ case T_ExplainStmt:
+ deparseExplainStmt(str, castNode(ExplainStmt, node));
+ break;
+ case T_FetchStmt:
+ deparseFetchStmt(str, castNode(FetchStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_GrantRoleStmt:
+ deparseGrantRoleStmt(str, castNode(GrantRoleStmt, node));
+ break;
+ case T_ImportForeignSchemaStmt:
+ deparseImportForeignSchemaStmt(str, castNode(ImportForeignSchemaStmt, node));
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_ListenStmt:
+ deparseListenStmt(str, castNode(ListenStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_LoadStmt:
+ deparseLoadStmt(str, castNode(LoadStmt, node));
+ break;
+ case T_LockStmt:
+ deparseLockStmt(str, castNode(LockStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ case T_PrepareStmt:
+ deparsePrepareStmt(str, castNode(PrepareStmt, node));
+ break;
+ case T_ReassignOwnedStmt:
+ deparseReassignOwnedStmt(str, castNode(ReassignOwnedStmt, node));
+ break;
+ case T_ReindexStmt:
+ deparseReindexStmt(str, castNode(ReindexStmt, node));
+ break;
+ case T_RenameStmt:
+ deparseRenameStmt(str, castNode(RenameStmt, node));
+ break;
+ case T_RuleStmt:
+ deparseRuleStmt(str, castNode(RuleStmt, node));
+ break;
+ case T_SecLabelStmt:
+ deparseSecLabelStmt(str, castNode(SecLabelStmt, node));
+ break;
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_TransactionStmt:
+ deparseTransactionStmt(str, castNode(TransactionStmt, node));
+ break;
+ case T_TruncateStmt:
+ deparseTruncateStmt(str, castNode(TruncateStmt, node));
+ break;
+ case T_UnlistenStmt:
+ deparseUnlistenStmt(str, castNode(UnlistenStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_VacuumStmt:
+ deparseVacuumStmt(str, castNode(VacuumStmt, node));
+ break;
+ case T_VariableSetStmt:
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, node));
+ break;
+ case T_VariableShowStmt:
+ deparseVariableShowStmt(str, castNode(VariableShowStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ // These node types are created by DefineStmt grammar for CREATE TYPE in some cases
+ case T_CompositeTypeStmt:
+ deparseCompositeTypeStmt(str, castNode(CompositeTypeStmt, node));
+ break;
+ case T_CreateEnumStmt:
+ deparseCreateEnumStmt(str, castNode(CreateEnumStmt, node));
+ break;
+ case T_CreateRangeStmt:
+ deparseCreateRangeStmt(str, castNode(CreateRangeStmt, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
+ }
+}
+#endif
diff --git a/postgres_deparse.13.c b/postgres_deparse.13.c
new file mode 100644
index 0000000..d144649
--- /dev/null
+++ b/postgres_deparse.13.c
@@ -0,0 +1,9938 @@
+#include "pg_config.h"
+#if(PG_MAJORVERSION_NUM == 13)
+
+// Adapted from https://raw.githubusercontent.com/pganalyze/libpg_query/refs/tags/13-2.2.0/src/pg_query_deparse.c
+
+// Copyright (c) 2015, Lukas Fittl
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "postgres.h"
+#include "catalog/index.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_trigger.h"
+#include "commands/trigger.h"
+#include "common/keywords.h"
+#include "common/kwlookup.h"
+#include "lib/stringinfo.h"
+#include "limits.h"
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "utils/builtins.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/xml.h"
+
+typedef enum DeparseNodeContext {
+ DEPARSE_NODE_CONTEXT_NONE,
+ // Parent node type (and sometimes field)
+ DEPARSE_NODE_CONTEXT_INSERT_RELATION,
+ DEPARSE_NODE_CONTEXT_INSERT_ON_CONFLICT,
+ DEPARSE_NODE_CONTEXT_UPDATE,
+ DEPARSE_NODE_CONTEXT_RETURNING,
+ DEPARSE_NODE_CONTEXT_A_EXPR,
+ DEPARSE_NODE_CONTEXT_XMLATTRIBUTES,
+ DEPARSE_NODE_CONTEXT_XMLNAMESPACES,
+ DEPARSE_NODE_CONTEXT_CREATE_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_TYPE,
+ // Identifier vs constant context
+ DEPARSE_NODE_CONTEXT_IDENTIFIER,
+ DEPARSE_NODE_CONTEXT_CONSTANT
+} DeparseNodeContext;
+
+static void
+removeTrailingSpace(StringInfo str)
+{
+ if (str->len >= 1 && str->data[str->len - 1] == ' ') {
+ str->len -= 1;
+ str->data[str->len] = '\0';
+ }
+}
+
+/*
+ * Append a SQL string literal representing "val" to buf.
+ *
+ * Copied here from postgres_fdw/deparse.c to avoid adding
+ * many additional dependencies.
+ */
+static void
+deparseStringLiteral(StringInfo buf, const char *val)
+{
+ const char *valptr;
+
+ /*
+ * Rather than making assumptions about the remote server's value of
+ * standard_conforming_strings, always use E'foo' syntax if there are any
+ * backslashes. This will fail on remote servers before 8.1, but those
+ * are long out of support.
+ */
+ if (strchr(val, '\\') != NULL)
+ appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
+ appendStringInfoChar(buf, '\'');
+ for (valptr = val; *valptr; valptr++)
+ {
+ char ch = *valptr;
+
+ if (SQL_STR_DOUBLE(ch, true))
+ appendStringInfoChar(buf, ch);
+ appendStringInfoChar(buf, ch);
+ }
+ appendStringInfoChar(buf, '\'');
+}
+
+// Check whether the value is a reserved keyword, to determine escaping for output
+//
+// Note that since the parser lowercases all keywords, this does *not* match when the
+// value is not all-lowercase and a reserved keyword.
+static bool
+isReservedKeyword(const char *val)
+{
+ int kwnum = ScanKeywordLookup(val, &ScanKeywords);
+ bool all_lower_case = true;
+ const char *cp;
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ (*cp >= 'a' && *cp <= 'z') ||
+ (*cp >= '0' && *cp <= '9') ||
+ (*cp == '_')))
+ {
+ all_lower_case = false;
+ break;
+ }
+ }
+
+ return all_lower_case && kwnum >= 0 && ScanKeywordCategories[kwnum] == RESERVED_KEYWORD;
+}
+
+// Returns whether the given value consists only of operator characters
+static bool
+isOp(const char *val)
+{
+ const char *cp;
+
+ Assert(strlen(val) > 0);
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ *cp == '~' ||
+ *cp == '!' ||
+ *cp == '@' ||
+ *cp == '#' ||
+ *cp == '^' ||
+ *cp == '&' ||
+ *cp == '|' ||
+ *cp == '`' ||
+ *cp == '?' ||
+ *cp == '+' ||
+ *cp == '-' ||
+ *cp == '*' ||
+ *cp == '/' ||
+ *cp == '%' ||
+ *cp == '<' ||
+ *cp == '>' ||
+ *cp == '='))
+ return false;
+ }
+
+ return true;
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt);
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause);
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context);
+static void deparseResTarget(StringInfo str, ResTarget *res_target, DeparseNodeContext context);
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt);
+static void deparseAlias(StringInfo str, Alias *alias);
+static void deparseWindowDef(StringInfo str, WindowDef* window_def);
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref);
+static void deparseSubLink(StringInfo str, SubLink* sub_link);
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context);
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr);
+static void deparseAStar(StringInfo str, A_Star* a_star);
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause);
+static void deparseSortBy(StringInfo str, SortBy* sort_by);
+static void deparseParamRef(StringInfo str, ParamRef* param_ref);
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function);
+static void deparseWithClause(StringInfo str, WithClause *with_clause);
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr);
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte);
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect);
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func);
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr * array_expr);
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr);
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast);
+static void deparseTypeName(StringInfo str, TypeName *type_name);
+static void deparseNullTest(StringInfo str, NullTest *null_test);
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr);
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when);
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection);
+static void deparseAIndices(StringInfo str, A_Indices *a_indices);
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr);
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test);
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def);
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt);
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause);
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem);
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt);
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt);
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause);
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default);
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt);
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt);
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter);
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec);
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt);
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt);
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt);
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample);
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func);
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set);
+static void deparseFuncCall(StringInfo str, FuncCall *func_call);
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr);
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr);
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize);
+static void deparseConstraint(StringInfo str, Constraint *constraint);
+static void deparseSchemaStmt(StringInfo str, Node *node);
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt);
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition);
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item);
+static void deparseAConst(StringInfo str, A_Const *a_const);
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr);
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func);
+
+static void deparsePreparableStmt(StringInfo str, Node *node);
+static void deparseRuleActionStmt(StringInfo str, Node *node);
+static void deparseExplainableStmt(StringInfo str, Node *node);
+static void deparseStmt(StringInfo str, Node *node);
+static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context);
+
+// "any_name" in gram.y
+static void deparseAnyName(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, parts)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipFirst(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, parts, 1)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipLast(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, parts)
+ {
+ if (lnext(parts, lc))
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (foreach_current_index(lc) < list_length(parts) - 2)
+ appendStringInfoChar(str, '.');
+ }
+ }
+}
+
+// "a_expr" / "b_expr" in gram.y
+static void deparseExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Expr:
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_NullTest:
+ deparseNullTest(str, castNode(NullTest, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_BoolExpr:
+ deparseBoolExpr(str, castNode(BoolExpr, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_SetToDefault:
+ deparseSetToDefault(str, castNode(SetToDefault, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CollateClause:
+ deparseCollateClause(str, castNode(CollateClause, node));
+ break;
+ case T_CurrentOfExpr:
+ deparseCurrentOfExpr(str, castNode(CurrentOfExpr, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_BooleanTest:
+ deparseBooleanTest(str, castNode(BooleanTest, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "c_expr" in gram.y
+static void deparseCExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_A_Expr:
+ appendStringInfoChar(str, '(');
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ')');
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in c_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "expr_list" in gram.y
+static void deparseExprList(StringInfo str, List *exprs)
+{
+ ListCell *lc;
+
+ foreach(lc, exprs)
+ {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
+static void deparseColId(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "ColLabel", "attr_name"
+//
+// Note this is kept separate from ColId in case we ever want to be more
+// specific on how to handle keywords here
+static void deparseColLabel(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "SignedIconst" and "Iconst" in gram.y
+static void deparseSignedIconst(StringInfo str, Node *node)
+{
+ appendStringInfo(str, "%d", intVal(node));
+}
+
+// "indirection" and "opt_indirection" in gram.y
+static void deparseOptIndirection(StringInfo str, List *indirection, int N)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, indirection, N)
+ {
+ if (IsA(lfirst(lc), String))
+ {
+ appendStringInfoChar(str, '.');
+ deparseColLabel(str, strVal(lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Star))
+ {
+ appendStringInfoString(str, ".*");
+ }
+ else if (IsA(lfirst(lc), A_Indices))
+ {
+ deparseAIndices(str, castNode(A_Indices, lfirst(lc)));
+ }
+ else
+ {
+ // No other nodes should appear here
+ Assert(false);
+ }
+ }
+}
+
+// "role_list" in gram.y
+static void deparseRoleList(StringInfo str, List *roles)
+{
+ ListCell *lc;
+
+ foreach(lc, roles)
+ {
+ RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
+ deparseRoleSpec(str, role_spec);
+ if (lnext(roles, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SimpleTypename" in gram.y
+static void deparseSimpleTypename(StringInfo str, Node *node)
+{
+ deparseTypeName(str, castNode(TypeName, node));
+}
+
+// "NumericOnly" in gram.y
+static void deparseNumericOnly(StringInfo str, Value *value)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ appendStringInfo(str, "%d", value->val.ival);
+ break;
+ case T_Float:
+ appendStringInfoString(str, value->val.str);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "NumericOnly_list" in gram.y
+static void deparseNumericOnlyList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseNumericOnly(str, (Value *) lfirst(lc));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SeqOptElem" in gram.y
+static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseSimpleTypename(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cache") == 0)
+ {
+ appendStringInfoString(str, "CACHE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NO CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "increment") == 0)
+ {
+ appendStringInfoString(str, "INCREMENT ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MAXVALUE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MAXVALUE");
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MINVALUE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MINVALUE");
+ }
+ else if (strcmp(def_elem->defname, "owned_by") == 0)
+ {
+ appendStringInfoString(str, "OWNED BY ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "sequence_name") == 0)
+ {
+ appendStringInfoString(str, "SEQUENCE NAME ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "start") == 0)
+ {
+ appendStringInfoString(str, "START ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "SeqOptList" in gram.y
+static void deparseSeqOptList(StringInfo str, List *options)
+{
+ ListCell *lc;
+ Assert(list_length(options) > 0);
+ foreach (lc, options)
+ {
+ deparseSeqOptElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "OptSeqOptList" in gram.y
+static void deparseOptSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ deparseSeqOptList(str, options);
+}
+
+// "OptParenthesizedSeqOptList" in gram.y
+static void deparseOptParenthesizedSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseSeqOptList(str, options);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "opt_drop_behavior" in gram.y
+static void deparseOptDropBehavior(StringInfo str, DropBehavior behavior)
+{
+ switch (behavior)
+ {
+ case DROP_RESTRICT:
+ // Default
+ break;
+ case DROP_CASCADE:
+ appendStringInfoString(str, "CASCADE ");
+ break;
+ }
+}
+
+// "any_operator" in gram.y
+static void deparseAnyOperator(StringInfo str, List *op)
+{
+ Assert(isOp(strVal(llast(op))));
+ if (list_length(op) == 2)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(linitial(op))));
+ appendStringInfoChar(str, '.');
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else if (list_length(op) == 1)
+ {
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "qual_Op" and "qual_all_Op" in gram.y
+static void deparseQualOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// "subquery_Op" in gram.y
+static void deparseSubqueryOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
+ {
+ appendStringInfoString(str, "LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
+ {
+ appendStringInfoString(str, "NOT LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
+ {
+ appendStringInfoString(str, "ILIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
+ {
+ appendStringInfoString(str, "NOT ILIKE");
+ }
+ else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// Not present directly in gram.y (usually matched by ColLabel)
+static void deparseGenericDefElemName(StringInfo str, const char *in)
+{
+ Assert(in != NULL);
+ char *val = pstrdup(in);
+ for (unsigned char *p = (unsigned char *) val; *p; p++)
+ *p = pg_toupper(*p);
+ appendStringInfoString(str, val);
+ pfree(val);
+}
+
+// "def_arg" and "operator_def_arg" in gram.y
+static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
+{
+ if (IsA(arg, TypeName)) // func_type
+ {
+ deparseTypeName(str, castNode(TypeName, arg));
+ }
+ else if (IsA(arg, List)) // qual_all_Op
+ {
+ List *l = castNode(List, arg);
+ Assert(list_length(l) == 1 || list_length(l) == 2);
+
+ // Schema qualified operator
+ if (list_length(l) == 2)
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, l);
+ appendStringInfoChar(str, ')');
+ }
+ else if (list_length(l) == 1)
+ {
+ appendStringInfoString(str, strVal(linitial(l)));
+ }
+ }
+ else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
+ {
+ deparseValue(str, (Value *) arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (IsA(arg, String))
+ {
+ char *s = strVal(arg);
+ if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) // NONE
+ {
+ appendStringInfoString(str, "NONE");
+ }
+ else if (isReservedKeyword(s)) // reserved_keyword
+ {
+ appendStringInfoString(str, s);
+ }
+ else // Sconst
+ {
+ deparseStringLiteral(str, s);
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "definition" in gram.y
+static void deparseDefinition(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL) {
+ appendStringInfoString(str, " = ");
+ deparseDefArg(str, def_elem->arg, false);
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "opt_definition" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptDefinition(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseDefinition(str, options);
+ }
+}
+
+// "create_generic_options" in gram.y
+static void deparseCreateGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ if (options == NULL)
+ return;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "common_func_opt_item" in gram.y
+static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "CALLED ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
+ {
+ appendStringInfoString(str, "IMMUTABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
+ {
+ appendStringInfoString(str, "STABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
+ {
+ appendStringInfoString(str, "VOLATILE");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "SECURITY DEFINER");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "SECURITY INVOKER");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOT LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "cost") == 0)
+ {
+ appendStringInfoString(str, "COST ");
+ deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "rows") == 0)
+ {
+ appendStringInfoString(str, "ROWS ");
+ deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "support") == 0)
+ {
+ appendStringInfoString(str, "SUPPORT ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
+ {
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "parallel") == 0)
+ {
+ appendStringInfoString(str, "PARALLEL ");
+ appendStringInfoString(str, quote_identifier(strVal(def_elem->arg)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "NonReservedWord_or_Sconst" in gram.y
+//
+// Note since both identifiers and string constants are allowed here, we
+// currently always return an identifier, except:
+//
+// 1) when the string is empty (since an empty identifier can't be scanned)
+// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
+static void deparseNonReservedWordOrSconst(StringInfo str, const char *val)
+{
+ if (strlen(val) == 0)
+ appendStringInfoString(str, "''");
+ else if (strlen(val) >= NAMEDATALEN)
+ deparseStringLiteral(str, val);
+ else
+ appendStringInfoString(str, quote_identifier(val));
+}
+
+// "func_as" in gram.y
+static void deparseFuncAs(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ char *strval = strVal(lfirst(lc));
+ if (strstr(strval, "$$") == NULL)
+ {
+ appendStringInfoString(str, "$$");
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, "$$");
+ }
+ else
+ {
+ deparseStringLiteral(str, strval);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createfunc_opt_item" in gram.y
+static void deparseCreateFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc = NULL;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseFuncAs(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "transform") == 0)
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, "TRANSFORM ");
+ foreach (lc, l)
+ {
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ else if (strcmp(def_elem->defname, "window") == 0)
+ {
+ appendStringInfoString(str, "WINDOW");
+ }
+ else
+ {
+ deparseCommonFuncOptItem(str, def_elem);
+ }
+}
+
+// "alter_generic_options" in gram.y
+static void deparseAlterGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ switch (def_elem->defaction)
+ {
+ case DEFELEM_UNSPEC:
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ break;
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "func_name" in gram.y
+static void deparseFuncName(StringInfo str, List *func_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, func_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(func_name, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "function_with_argtypes" in gram.y
+static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ if (!object_with_args->args_unspecified)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, object_with_args->objargs)
+ {
+ if (IsA(lfirst(lc), TypeName))
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ else
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ if (lnext(object_with_args->objargs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "function_with_argtypes_list" in gram.y
+static void deparseFunctionWithArgtypesList(StringInfo str, List *l)
+{
+ ListCell *lc;
+
+ foreach(lc, l)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "operator_with_argtypes" in gram.y
+static void deparseOperatorWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ deparseAnyOperator(str, object_with_args->objname);
+
+ Assert(list_length(object_with_args->objargs) == 2);
+ appendStringInfoChar(str, '(');
+ if (linitial(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, linitial(object_with_args->objargs)));
+ appendStringInfoString(str, ", ");
+ if (lsecond(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, lsecond(object_with_args->objargs)));
+ appendStringInfoChar(str, ')');
+}
+
+// "aggr_args" in gram.y
+static void deparseAggrArgs(StringInfo str, List *aggr_args)
+{
+ Assert(list_length(aggr_args) == 2);
+
+ ListCell *lc = NULL;
+ List *args = linitial(aggr_args);
+ int order_by_pos = intVal(lsecond(aggr_args));
+
+ appendStringInfoChar(str, '(');
+ if (args == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, args)
+ {
+ if (foreach_current_index(lc) == order_by_pos)
+ {
+ if (foreach_current_index(lc) > 0)
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, "ORDER BY ");
+ }
+ else if (foreach_current_index(lc) > 0)
+ {
+ appendStringInfoString(str, ", ");
+ }
+
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ }
+
+ // Repeat the last direct arg as a ordered arg to handle the
+ // simplification done by makeOrderedSetArgs in gram.y
+ if (order_by_pos == list_length(args))
+ {
+ appendStringInfoString(str, " ORDER BY ");
+ deparseFunctionParameter(str, castNode(FunctionParameter, llast(args)));
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "aggregate_with_argtypes" in gram.y
+static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc = NULL;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ appendStringInfoChar(str, '(');
+ if (object_with_args->objargs == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, object_with_args->objargs)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(object_with_args->objargs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "columnList" in gram.y
+static void deparseColumnList(StringInfo str, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(columns, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptTemp" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptTemp(StringInfo str, char relpersistence)
+{
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_PERMANENT:
+ // Default
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ appendStringInfoString(str, "UNLOGGED ");
+ break;
+ case RELPERSISTENCE_TEMP:
+ appendStringInfoString(str, "TEMPORARY ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+// "relation_expr_list" in gram.y
+static void deparseRelationExprList(StringInfo str, List *relation_exprs)
+{
+ ListCell *lc = NULL;
+ foreach(lc, relation_exprs)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(relation_exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "handler_name" in gram.y
+static void deparseHandlerName(StringInfo str, List *handler_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, handler_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(handler_name, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "fdw_options" in gram.y
+static void deparseFdwOptions(StringInfo str, List *fdw_options)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, fdw_options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO HANDLER ");
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO VALIDATOR ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(fdw_options, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "type_list" in gram.y
+static void deparseTypeList(StringInfo str, List *type_list)
+{
+ ListCell *lc = NULL;
+ foreach(lc, type_list)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(type_list, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_boolean_or_string" in gram.y
+static void deparseOptBooleanOrString(StringInfo str, char *s)
+{
+ if (s == NULL)
+ return; // No value set
+ else if (strcmp(s, "true") == 0)
+ appendStringInfoString(str, "TRUE");
+ else if (strcmp(s, "false") == 0)
+ appendStringInfoString(str, "FALSE");
+ else if (strcmp(s, "on") == 0)
+ appendStringInfoString(str, "ON");
+ else if (strcmp(s, "off") == 0)
+ appendStringInfoString(str, "OFF");
+ else
+ deparseNonReservedWordOrSconst(str, s);
+}
+
+// "var_name"
+//
+// Note this is kept separate from ColId in case we want to improve the
+// output of namespaced variable names
+static void deparseVarName(StringInfo str, char *s)
+{
+ deparseColId(str, s);
+}
+
+// "var_list"
+static void deparseVarList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, lfirst(lc));
+ if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
+ deparseNumericOnly(str, (Value *) &a_const->val);
+ else if (IsA(&a_const->val, String))
+ deparseOptBooleanOrString(str, strVal(&a_const->val));
+ else
+ Assert(false);
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "transaction_mode_list" in gram.y
+static void deparseTransactionModeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "transaction_isolation") == 0)
+ {
+ char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
+ appendStringInfoString(str, "ISOLATION LEVEL ");
+ if (strcmp(s, "read uncommitted") == 0)
+ appendStringInfoString(str, "READ UNCOMMITTED");
+ else if (strcmp(s, "read committed") == 0)
+ appendStringInfoString(str, "READ COMMITTED");
+ else if (strcmp(s, "repeatable read") == 0)
+ appendStringInfoString(str, "REPEATABLE READ");
+ else if (strcmp(s, "serializable") == 0)
+ appendStringInfoString(str, "SERIALIZABLE");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "READ ONLY");
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "READ WRITE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "DEFERRABLE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "NOT DEFERRABLE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "alter_identity_column_option_list" in gram.y
+static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "generated") == 0)
+ {
+ appendStringInfoString(str, "SET GENERATED ");
+ if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
+ appendStringInfoString(str, "ALWAYS");
+ else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+ appendStringInfoString(str, "BY DEFAULT");
+ else
+ Assert(false);
+ }
+ else
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSeqOptElem(str, def_elem);
+ }
+ if (lnext(l, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "reloptions" in gram.y
+static void deparseRelOptions(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (def_elem->defnamespace != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defnamespace));
+ appendStringInfoChar(str, '.');
+ }
+ if (def_elem->defname != NULL)
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->defname != NULL && def_elem->arg != NULL)
+ appendStringInfoChar(str, '=');
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, false);
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "OptWith" and "opt_reloptions" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptWith(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseRelOptions(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "target_list" and "opt_target_list" in gram.y
+static void deparseTargetList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+
+ if (res_target->val == NULL)
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
+ else if (IsA(res_target->val, ColumnRef))
+ deparseColumnRef(str, castNode(ColumnRef, res_target->val));
+ else
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL) {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "insert_column_list" in gram.y
+static void deparseInsertColumnList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->name != NULL);
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ deparseOptIndirection(str, res_target->indirection, 0);
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_attribute_list" in gram.y
+static void deparseXmlAttributeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_namespace_list" in gram.y
+static void deparseXmlNamespaceList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (res_target->name == NULL)
+ appendStringInfoString(str, "DEFAULT ");
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "table_ref" in gram.y
+static void deparseTableRef(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_RangeVar:
+ deparseRangeVar(str, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_RangeTableSample:
+ deparseRangeTableSample(str, castNode(RangeTableSample, node));
+ break;
+ case T_RangeFunction:
+ deparseRangeFunction(str, castNode(RangeFunction, node));
+ break;
+ case T_RangeTableFunc:
+ deparseRangeTableFunc(str, castNode(RangeTableFunc, node));
+ break;
+ case T_RangeSubselect:
+ deparseRangeSubselect(str, castNode(RangeSubselect, node));
+ break;
+ case T_JoinExpr:
+ deparseJoinExpr(str, castNode(JoinExpr, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "from_list" in gram.y
+static void deparseFromList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseTableRef(str, lfirst(lc));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "from_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseFromClause(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseFromList(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "where_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereClause(StringInfo str, Node *node)
+{
+ if (node != NULL)
+ {
+ appendStringInfoString(str, "WHERE ");
+ deparseExpr(str, node);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "group_by_list" in gram.y
+static void deparseGroupByList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), GroupingSet))
+ deparseGroupingSet(str, castNode(GroupingSet, lfirst(lc)));
+ else
+ deparseExpr(str, lfirst(lc));
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "set_target" in gram.y
+static void deparseSetTarget(StringInfo str, ResTarget *res_target)
+{
+ Assert(res_target->name != NULL);
+ deparseColId(str, res_target->name);
+ deparseOptIndirection(str, res_target->indirection, 0);
+}
+
+// "any_name_list" in gram.y
+static void deparseAnyNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseAnyName(str, castNode(List, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "name_list" in gram.y
+static void deparseNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseColId(str, strVal(lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_sort_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptSortClause(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "ORDER BY ");
+
+ foreach(lc, l)
+ {
+ deparseSortBy(str, castNode(SortBy, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "func_arg_expr" in gram.y
+static void deparseFuncArgExpr(StringInfo str, Node *node)
+{
+ if (IsA(node, NamedArgExpr))
+ {
+ NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
+ appendStringInfoString(str, named_arg_expr->name);
+ appendStringInfoString(str, " := ");
+ deparseExpr(str, (Node *) named_arg_expr->arg);
+ }
+ else
+ {
+ deparseExpr(str, node);
+ }
+}
+
+// "set_clause_list" in gram.y
+static void deparseSetClauseList(StringInfo str, List *target_list)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ int skip_next_n_elems = 0;
+
+ Assert(list_length(target_list) > 0);
+
+ foreach(lc, target_list)
+ {
+ if (skip_next_n_elems > 0)
+ {
+ skip_next_n_elems--;
+ continue;
+ }
+
+ if (foreach_current_index(lc) != 0)
+ appendStringInfoString(str, ", ");
+
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (IsA(res_target->val, MultiAssignRef))
+ {
+ MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
+ appendStringInfoString(str, "(");
+ for_each_cell(lc2, target_list, lc)
+ {
+ deparseSetTarget(str, castNode(ResTarget, lfirst(lc2)));
+ if (foreach_current_index(lc2) == r->ncolumns - 1) // Last element in this multi-assign
+ break;
+ else if (lnext(target_list, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") = ");
+ deparseExpr(str, r->source);
+ skip_next_n_elems = r->ncolumns - 1;
+ }
+ else
+ {
+ deparseSetTarget(str, res_target);
+ appendStringInfoString(str, " = ");
+ deparseExpr(str, res_target->val);
+ }
+ }
+}
+
+// "func_expr_windowless" in gram.y
+static void deparseFuncExprWindowless(StringInfo str, Node* node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "opt_collate" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptCollate(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "index_elem" in gram.y
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem)
+{
+ if (index_elem->name != NULL)
+ {
+ deparseColId(str, index_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (index_elem->expr != NULL)
+ {
+ switch (nodeTag(index_elem->expr))
+ {
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_TypeCast:
+ case T_CoalesceExpr:
+ case T_MinMaxExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ deparseFuncExprWindowless(str, index_elem->expr);
+ break;
+ default:
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, index_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseOptCollate(str, index_elem->collation);
+
+ if (list_length(index_elem->opclass) > 0)
+ {
+ deparseAnyName(str, index_elem->opclass);
+
+ if (list_length(index_elem->opclassopts) > 0)
+ deparseRelOptions(str, index_elem->opclassopts);
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (index_elem->ordering)
+ {
+ case SORTBY_DEFAULT:
+ // Default
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ // Not allowed in CREATE INDEX
+ Assert(false);
+ break;
+ }
+
+ switch (index_elem->nulls_ordering)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ // Default
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+// "qualified_name_list" in gram.y
+static void deparseQualifiedNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptInherit" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptInherit(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "INHERITS (");
+ deparseQualifiedNameList(str, l);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+// "privilege_target" in gram.y
+static void deparsePrivilegeTarget(StringInfo str, GrantTargetType targtype, ObjectType objtype, List *objs)
+{
+ switch (targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "FOREIGN SERVER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyNameList(str, objs);
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnlyList(str, objs);
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "ALL TABLES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "ALL SEQUENCES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "ALL FUNCTIONS IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "ALL PROCEDURES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ALL ROUTINES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_DEFAULTS: // defacl_privilege_target
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLES");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTIONS");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPES");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMAS");
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ }
+}
+
+// "opclass_item_list" in gram.y
+static void deparseOpclassItemList(StringInfo str, List *items)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, items)
+ {
+ deparseCreateOpClassItem(str, castNode(CreateOpClassItem, lfirst(lc)));
+ if (lnext(items, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createdb_opt_list" in gram.y
+static void deparseCreatedbOptList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "connection_limit") == 0)
+ appendStringInfoString(str, "CONNECTION LIMIT");
+ else
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ appendStringInfoString(str, "DEFAULT");
+ else if (IsA(def_elem->arg, Integer))
+ deparseSignedIconst(str, def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+
+ if (lnext(l, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
+{
+ const ListCell *lc = NULL;
+ const ListCell *lc2 = NULL;
+
+ if (stmt->withClause)
+ {
+ deparseWithClause(str, stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (stmt->op) {
+ case SETOP_NONE:
+ if (list_length(stmt->valuesLists) > 0)
+ {
+ const ListCell *lc;
+ appendStringInfoString(str, "VALUES ");
+
+ foreach(lc, stmt->valuesLists)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, lfirst(lc));
+ appendStringInfoChar(str, ')');
+ if (lnext(stmt->valuesLists, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ }
+
+ appendStringInfoString(str, "SELECT ");
+
+ if (list_length(stmt->targetList) > 0)
+ {
+ if (stmt->distinctClause != NULL)
+ {
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
+ {
+ appendStringInfoString(str, "ON (");
+ deparseExprList(str, stmt->distinctClause);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ deparseTargetList(str, stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->intoClause != NULL)
+ {
+ appendStringInfoString(str, "INTO ");
+ deparseOptTemp(str, stmt->intoClause->rel->relpersistence);
+ deparseIntoClause(str, stmt->intoClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, stmt->fromClause);
+ deparseWhereClause(str, stmt->whereClause);
+
+ if (list_length(stmt->groupClause) > 0)
+ {
+ appendStringInfoString(str, "GROUP BY ");
+ deparseGroupByList(str, stmt->groupClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->havingClause != NULL)
+ {
+ appendStringInfoString(str, "HAVING ");
+ deparseExpr(str, stmt->havingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->windowClause != NULL)
+ {
+ appendStringInfoString(str, "WINDOW ");
+ foreach(lc, stmt->windowClause)
+ {
+ WindowDef *window_def = castNode(WindowDef, lfirst(lc));
+ Assert(window_def->name != NULL);
+ appendStringInfoString(str, window_def->name);
+ appendStringInfoString(str, " AS ");
+ deparseWindowDef(str, window_def);
+ if (lnext(stmt->windowClause, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case SETOP_UNION:
+ case SETOP_INTERSECT:
+ case SETOP_EXCEPT:
+ {
+ bool need_larg_parens =
+ list_length(stmt->larg->sortClause) > 0 ||
+ stmt->larg->limitOffset != NULL ||
+ stmt->larg->limitCount != NULL ||
+ list_length(stmt->larg->lockingClause) > 0 ||
+ stmt->larg->withClause != NULL ||
+ stmt->larg->op != SETOP_NONE;
+ bool need_rarg_parens =
+ list_length(stmt->rarg->sortClause) > 0 ||
+ stmt->rarg->limitOffset != NULL ||
+ stmt->rarg->limitCount != NULL ||
+ list_length(stmt->rarg->lockingClause) > 0 ||
+ stmt->rarg->withClause != NULL ||
+ stmt->rarg->op != SETOP_NONE;
+ if (need_larg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->larg);
+ if (need_larg_parens)
+ appendStringInfoChar(str, ')');
+ switch (stmt->op)
+ {
+ case SETOP_UNION:
+ appendStringInfoString(str, " UNION ");
+ break;
+ case SETOP_INTERSECT:
+ appendStringInfoString(str, " INTERSECT ");
+ break;
+ case SETOP_EXCEPT:
+ appendStringInfoString(str, " EXCEPT ");
+ break;
+ default:
+ Assert(false);
+ }
+ if (stmt->all)
+ appendStringInfoString(str, "ALL ");
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ }
+
+ deparseOptSortClause(str, stmt->sortClause);
+
+ if (stmt->limitCount != NULL)
+ {
+ if (stmt->limitOption == LIMIT_OPTION_COUNT)
+ appendStringInfoString(str, "LIMIT ");
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ appendStringInfoString(str, "FETCH FIRST ");
+
+ if (IsA(stmt->limitCount, A_Const) && IsA(&castNode(A_Const, stmt->limitCount)->val, Null))
+ appendStringInfoString(str, "ALL");
+ else
+ deparseCExpr(str, stmt->limitCount);
+
+ appendStringInfoChar(str, ' ');
+
+ if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ appendStringInfoString(str, "ROWS WITH TIES ");
+ }
+
+ if (stmt->limitOffset != NULL)
+ {
+ appendStringInfoString(str, "OFFSET ");
+ deparseExpr(str, stmt->limitOffset);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(stmt->lockingClause) > 0)
+ {
+ foreach(lc, stmt->lockingClause)
+ {
+ deparseLockingClause(str, castNode(LockingClause, lfirst(lc)));
+ if (lnext(stmt->lockingClause, lc))
+ appendStringInfoString(str, " ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause)
+{
+ ListCell *lc;
+
+ deparseRangeVar(str, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE); /* target relation name */
+
+ if (list_length(into_clause->colNames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, into_clause->colNames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (into_clause->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(into_clause->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptWith(str, into_clause->options);
+
+ switch (into_clause->onCommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (into_clause->tableSpaceName != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(into_clause->tableSpaceName));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context)
+{
+ if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ONLY ");
+
+ if (range_var->catalogname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->catalogname));
+ appendStringInfoChar(str, '.');
+ }
+
+ if (range_var->schemaname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->schemaname));
+ appendStringInfoChar(str, '.');
+ }
+
+ Assert(range_var->relname != NULL);
+ appendStringInfoString(str, quote_identifier(range_var->relname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_var->alias != NULL)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_var->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt)
+{
+ if (raw_stmt->stmt == NULL)
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
+
+ deparseStmt(str, raw_stmt->stmt);
+}
+
+static void deparseAlias(StringInfo str, Alias *alias)
+{
+ appendStringInfoString(str, quote_identifier(alias->aliasname));
+
+ if (list_length(alias->colnames) > 0)
+ {
+ const ListCell *lc = NULL;
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, alias->colnames);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseAConst(StringInfo str, A_Const *a_const)
+{
+ deparseValue(str, &a_const->val, DEPARSE_NODE_CONTEXT_CONSTANT);
+}
+
+static void deparseFuncCall(StringInfo str, FuncCall *func_call)
+{
+ const ListCell *lc = NULL;
+
+ Assert(list_length(func_call->funcname) > 0);
+
+ if (list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "OVERLAY(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PLACING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ deparseFuncName(str, func_call->funcname);
+ appendStringInfoChar(str, '(');
+
+ if (func_call->agg_distinct)
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (func_call->agg_star)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (list_length(func_call->args) > 0)
+ {
+ foreach(lc, func_call->args)
+ {
+ if (func_call->func_variadic && !lnext(func_call->args, lc))
+ appendStringInfoString(str, "VARIADIC ");
+ deparseFuncArgExpr(str, lfirst(lc));
+ if (lnext(func_call->args, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (func_call->agg_order != NULL && !func_call->agg_within_group)
+ {
+ deparseOptSortClause(str, func_call->agg_order);
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+
+ if (func_call->agg_order != NULL && func_call->agg_within_group)
+ {
+ appendStringInfoString(str, "WITHIN GROUP (");
+ deparseOptSortClause(str, func_call->agg_order);
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->agg_filter)
+ {
+ appendStringInfoString(str, "FILTER (WHERE ");
+ deparseExpr(str, func_call->agg_filter);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->over)
+ {
+ appendStringInfoString(str, "OVER ");
+ if (func_call->over->name)
+ appendStringInfoString(str, func_call->over->name);
+ else
+ deparseWindowDef(str, func_call->over);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseWindowDef(StringInfo str, WindowDef* window_def)
+{
+ ListCell *lc;
+
+ // The parent node is responsible for outputting window_def->name
+
+ appendStringInfoChar(str, '(');
+
+ if (window_def->refname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(window_def->refname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(window_def->partitionClause) > 0)
+ {
+ appendStringInfoString(str, "PARTITION BY ");
+ deparseExprList(str, window_def->partitionClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptSortClause(str, window_def->orderClause);
+
+ if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
+ {
+ if (window_def->frameOptions & FRAMEOPTION_RANGE)
+ appendStringInfoString(str, "RANGE ");
+ else if (window_def->frameOptions & FRAMEOPTION_ROWS)
+ appendStringInfoString(str, "ROWS ");
+ else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
+ appendStringInfoString(str, "GROUPS ");
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ appendStringInfoString(str, "BETWEEN ");
+
+ // frame_start
+ if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ {
+ appendStringInfoString(str, "UNBOUNDED PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ {
+ appendStringInfoString(str, "AND ");
+
+ // frame_end
+ if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
+ {
+ appendStringInfoString(str, "UNBOUNDED FOLLOWING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
+ appendStringInfoString(str, "EXCLUDE CURRENT ROW ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
+ appendStringInfoString(str, "EXCLUDE GROUP ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
+ appendStringInfoString(str, "EXCLUDE TIES ");
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref)
+{
+ Assert(list_length(column_ref->fields) >= 1);
+
+ if (IsA(linitial(column_ref->fields), A_Star))
+ deparseAStar(str, castNode(A_Star, linitial(column_ref->fields)));
+ else if (IsA(linitial(column_ref->fields), String))
+ deparseColLabel(str, strVal(linitial(column_ref->fields)));
+
+ deparseOptIndirection(str, column_ref->fields, 1);
+}
+
+static void deparseSubLink(StringInfo str, SubLink* sub_link)
+{
+ switch (sub_link->subLinkType) {
+ case EXISTS_SUBLINK:
+ appendStringInfoString(str, "EXISTS (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ALL_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ALL (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ANY_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ if (list_length(sub_link->operName) > 0)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ANY ");
+ }
+ else
+ {
+ appendStringInfoString(str, " IN ");
+ }
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ROWCOMPARE_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case EXPR_SUBLINK:
+ appendStringInfoString(str, "(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case MULTIEXPR_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case ARRAY_SUBLINK:
+ appendStringInfoString(str, "ARRAY(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case CTE_SUBLINK: /* for SubPlans only */
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context)
+{
+ ListCell *lc;
+ char *name;
+
+ bool need_lexpr_parens = a_expr->lexpr != NULL && (IsA(a_expr->lexpr, BoolExpr) || IsA(a_expr->lexpr, NullTest) || IsA(a_expr->lexpr, A_Expr));
+ bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
+
+ switch (a_expr->kind) {
+ case AEXPR_OP: /* normal operator */
+ {
+ bool need_outer_parens = context == DEPARSE_NODE_CONTEXT_A_EXPR;
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, '(');
+ if (a_expr->lexpr != NULL)
+ {
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ deparseQualOp(str, a_expr->name);
+ if (a_expr->rexpr != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ }
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, ')');
+ }
+ return;
+ case AEXPR_OP_ANY: /* scalar op ANY (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ANY(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OP_ALL: /* scalar op ALL (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ALL(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoString(str, " IS DISTINCT FROM ");
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, " IS NOT DISTINCT FROM ");
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_NULLIF: /* NULLIF - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ appendStringInfoString(str, "NULLIF(");
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OF: /* IS [NOT] OF - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IS OF ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "IS NOT OF ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IN ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "NOT IN ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ if (IsA(a_expr->rexpr, SubLink))
+ deparseSubLink(str, castNode(SubLink, a_expr->rexpr));
+ else
+ deparseExprList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~~") == 0) {
+ appendStringInfoString(str, "LIKE ");
+ } else if (strcmp(name, "!~~") == 0) {
+ appendStringInfoString(str, "NOT LIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~~*") == 0) {
+ appendStringInfoString(str, "ILIKE ");
+ } else if (strcmp(name, "!~~*") == 0) {
+ appendStringInfoString(str, "NOT ILIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~") == 0) {
+ appendStringInfoString(str, "SIMILAR TO ");
+ } else if (strcmp(name, "!~") == 0) {
+ appendStringInfoString(str, "NOT SIMILAR TO ");
+ } else {
+ Assert(false);
+ }
+
+ FuncCall *n = castNode(FuncCall, a_expr->rexpr);
+ Assert(list_length(n->funcname) == 2);
+ Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
+ Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
+ Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
+
+ deparseExpr(str, linitial(n->args));
+ if (list_length(n->args) == 2)
+ {
+ appendStringInfoString(str, " ESCAPE ");
+ deparseExpr(str, lsecond(n->args));
+ }
+
+ return;
+ case AEXPR_BETWEEN: /* name must be "BETWEEN" */
+ case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
+ case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
+ case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, strVal(linitial(a_expr->name)));
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, castNode(List, a_expr->rexpr)) {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(castNode(List, a_expr->rexpr), lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case AEXPR_PAREN: /* nameless dummy node for parentheses */
+ // Not present in parse trees when operator_precedence_warning is turned off
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr)
+{
+ const ListCell *lc = NULL;
+ switch (bool_expr->boolop)
+ {
+ case AND_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(bool_expr->args, lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case OR_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(bool_expr->args, lc))
+ appendStringInfoString(str, " OR ");
+ }
+ return;
+ case NOT_EXPR:
+ Assert(list_length(bool_expr->args) == 1);
+ bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
+ appendStringInfoString(str, "NOT ");
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(bool_expr->args));
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ }
+}
+
+static void deparseAStar(StringInfo str, A_Star *a_star)
+{
+ appendStringInfoChar(str, '*');
+}
+
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause)
+{
+ ListCell *lc;
+ if (collate_clause->arg != NULL)
+ {
+ bool need_parens = IsA(collate_clause->arg, A_Expr);
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, collate_clause->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, collate_clause->collname);
+}
+
+static void deparseSortBy(StringInfo str, SortBy* sort_by)
+{
+ deparseExpr(str, sort_by->node);
+ appendStringInfoChar(str, ' ');
+
+ switch (sort_by->sortby_dir)
+ {
+ case SORTBY_DEFAULT:
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ appendStringInfoString(str, "USING ");
+ deparseQualOp(str, sort_by->useOp);
+ break;
+ }
+
+ switch (sort_by->sortby_nulls)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseParamRef(StringInfo str, ParamRef* param_ref)
+{
+ if (param_ref->number == 0) {
+ appendStringInfoChar(str, '?');
+ } else {
+ appendStringInfo(str, "$%d", param_ref->number);
+ }
+}
+
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function)
+{
+ switch (sql_value_function->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ appendStringInfoString(str, "current_date");
+ break;
+ case SVFOP_CURRENT_TIME:
+ appendStringInfoString(str, "current_time");
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ appendStringInfoString(str, "current_time"); // with precision
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ appendStringInfoString(str, "current_timestamp");
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ appendStringInfoString(str, "current_timestamp"); // with precision
+ break;
+ case SVFOP_LOCALTIME:
+ appendStringInfoString(str, "localtime");
+ break;
+ case SVFOP_LOCALTIME_N:
+ appendStringInfoString(str, "localtime"); // with precision
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ appendStringInfoString(str, "localtimestamp");
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ appendStringInfoString(str, "localtimestamp"); // with precision
+ break;
+ case SVFOP_CURRENT_ROLE:
+ appendStringInfoString(str, "current_role");
+ break;
+ case SVFOP_CURRENT_USER:
+ appendStringInfoString(str, "current_user");
+ break;
+ case SVFOP_USER:
+ appendStringInfoString(str, "user");
+ break;
+ case SVFOP_SESSION_USER:
+ appendStringInfoString(str, "session_user");
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ appendStringInfoString(str, "current_catalog");
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ appendStringInfoString(str, "current_schema");
+ break;
+ }
+
+ if (sql_value_function->typmod != -1)
+ {
+ appendStringInfo(str, "(%d)", sql_value_function->typmod);
+ }
+}
+
+static void deparseWithClause(StringInfo str, WithClause *with_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "WITH ");
+ if (with_clause->recursive)
+ appendStringInfoString(str, "RECURSIVE ");
+
+ foreach(lc, with_clause->ctes) {
+ deparseCommonTableExpr(str, castNode(CommonTableExpr, lfirst(lc)));
+ if (lnext(with_clause->ctes, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
+{
+ ListCell *lc;
+ bool need_alias_parens = join_expr->alias != NULL;
+ bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
+
+ if (need_alias_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseTableRef(str, join_expr->larg);
+
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->isNatural)
+ appendStringInfoString(str, "NATURAL ");
+
+ switch (join_expr->jointype)
+ {
+ case JOIN_INNER: /* matching tuple pairs only */
+ if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
+ appendStringInfoString(str, "CROSS ");
+ break;
+ case JOIN_LEFT: /* pairs + unmatched LHS tuples */
+ appendStringInfoString(str, "LEFT ");
+ break;
+ case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
+ appendStringInfoString(str, "FULL ");
+ break;
+ case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
+ appendStringInfoString(str, "RIGHT ");
+ break;
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ case JOIN_UNIQUE_OUTER:
+ case JOIN_UNIQUE_INNER:
+ // Only used by the planner/executor, not seen in parser output
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "JOIN ");
+
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseTableRef(str, join_expr->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->quals != NULL)
+ {
+ appendStringInfoString(str, "ON ");
+ deparseExpr(str, join_expr->quals);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(join_expr->usingClause) > 0)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseNameList(str, join_expr->usingClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (need_alias_parens)
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->alias != NULL)
+ deparseAlias(str, join_expr->alias);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
+{
+ deparseColId(str, cte->ctename);
+
+ if (list_length(cte->aliascolnames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, cte->aliascolnames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ switch (cte->ctematerialized) {
+ case CTEMaterializeDefault: /* no option specified */
+ break;
+ case CTEMaterializeAlways:
+ appendStringInfoString(str, "MATERIALIZED ");
+ break;
+ case CTEMaterializeNever:
+ appendStringInfoString(str, "NOT MATERIALIZED ");
+ break;
+ }
+
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, cte->ctequery);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
+{
+ if (range_subselect->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, range_subselect->subquery));
+ appendStringInfoChar(str, ')');
+
+ if (range_subselect->alias != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseAlias(str, range_subselect->alias);
+ }
+}
+
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (range_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ if (range_func->is_rowsfrom)
+ {
+ appendStringInfoString(str, "ROWS FROM ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->functions)
+ {
+ List *lfunc = castNode(List, lfirst(lc));
+ Assert(list_length(lfunc) == 2);
+ deparseFuncExprWindowless(str, linitial(lfunc));
+ appendStringInfoChar(str, ' ');
+ List *coldeflist = castNode(List, lsecond(lfunc));
+ if (list_length(coldeflist) > 0)
+ {
+ appendStringInfoString(str, "AS (");
+ foreach(lc2, coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc2)));
+ if (lnext(coldeflist, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ if (lnext(range_func->functions, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(list_length(linitial(range_func->functions)) == 2);
+ deparseFuncExprWindowless(str, linitial(linitial(range_func->functions)));
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (range_func->ordinality)
+ appendStringInfoString(str, "WITH ORDINALITY ");
+
+ if (range_func->alias != NULL)
+ {
+ deparseAlias(str, range_func->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(range_func->coldeflist) > 0)
+ {
+ if (range_func->alias == NULL)
+ appendStringInfoString(str, "AS ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(range_func->coldeflist, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr *array_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ARRAY[");
+ deparseExprList(str, array_expr->elements);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
+{
+ ListCell *lc;
+
+ switch (row_expr->row_format)
+ {
+ case COERCE_EXPLICIT_CALL:
+ appendStringInfoString(str, "ROW");
+ break;
+ case COERCE_EXPLICIT_CAST:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCE_IMPLICIT_CAST:
+ // No prefix
+ break;
+ }
+
+ appendStringInfoString(str, "(");
+ deparseExprList(str, row_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
+{
+ bool need_parens = false;
+
+ Assert(type_cast->typeName != NULL);
+
+ if (IsA(type_cast->arg, A_Expr))
+ {
+ appendStringInfoString(str, "CAST(");
+ deparseExpr(str, type_cast->arg);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, type_cast->typeName);
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ if (IsA(type_cast->arg, A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, type_cast->arg);
+
+ if (list_length(type_cast->typeName->names) == 2 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
+ {
+ char *typename = strVal(lsecond(type_cast->typeName->names));
+ if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
+ {
+ appendStringInfoString(str, "char ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
+ {
+ /*
+ * Handle "bool" or "false" in the statement, which is represented as a typecast
+ * (other boolean casts should be represented as a cast, i.e. don't need special handling)
+ */
+ char *const_val = strVal(&a_const->val);
+ if (strcmp(const_val, "t") == 0)
+ {
+ appendStringInfoString(str, "true");
+ return;
+ }
+ if (strcmp(const_val, "f") == 0)
+ {
+ appendStringInfoString(str, "false");
+ return;
+ }
+ }
+ }
+
+ // Ensure negative values have wrapping parentheses
+ if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
+ {
+ need_parens = true;
+ }
+ }
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, type_cast->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, "::");
+ deparseTypeName(str, type_cast->typeName);
+}
+
+static void deparseTypeName(StringInfo str, TypeName *type_name)
+{
+ ListCell *lc;
+ bool skip_typmods = false;
+
+ if (type_name->setof)
+ appendStringInfoString(str, "SETOF ");
+
+ if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
+ {
+ const char *name = strVal(lsecond(type_name->names));
+ if (strcmp(name, "bpchar") == 0)
+ {
+ appendStringInfoString(str, "char");
+ }
+ else if (strcmp(name, "varchar") == 0)
+ {
+ appendStringInfoString(str, "varchar");
+ }
+ else if (strcmp(name, "numeric") == 0)
+ {
+ appendStringInfoString(str, "numeric");
+ }
+ else if (strcmp(name, "bool") == 0)
+ {
+ appendStringInfoString(str, "boolean");
+ }
+ else if (strcmp(name, "int2") == 0)
+ {
+ appendStringInfoString(str, "smallint");
+ }
+ else if (strcmp(name, "int4") == 0)
+ {
+ appendStringInfoString(str, "int");
+ }
+ else if (strcmp(name, "int8") == 0)
+ {
+ appendStringInfoString(str, "bigint");
+ }
+ else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
+ {
+ appendStringInfoString(str, "real");
+ }
+ else if (strcmp(name, "float8") == 0)
+ {
+ appendStringInfoString(str, "double precision");
+ }
+ else if (strcmp(name, "time") == 0)
+ {
+ appendStringInfoString(str, "time");
+ }
+ else if (strcmp(name, "timetz") == 0)
+ {
+ appendStringInfoString(str, "time ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "timestamp") == 0)
+ {
+ appendStringInfoString(str, "timestamp");
+ }
+ else if (strcmp(name, "timestamptz") == 0)
+ {
+ appendStringInfoString(str, "timestamp ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
+ {
+ appendStringInfoString(str, "interval");
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
+ {
+ Assert(IsA(linitial(type_name->typmods), A_Const));
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
+
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
+
+ appendStringInfoString(str, "interval");
+
+ // This logic is based on intervaltypmodout in timestamp.c
+ switch (fields)
+ {
+ case INTERVAL_MASK(YEAR):
+ appendStringInfoString(str, " year");
+ break;
+ case INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " month");
+ break;
+ case INTERVAL_MASK(DAY):
+ appendStringInfoString(str, " day");
+ break;
+ case INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " hour");
+ break;
+ case INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " minute");
+ break;
+ case INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " second");
+ break;
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " year to month");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " day to hour");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " day to minute");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " day to second");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " hour to minute");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " hour to second");
+ break;
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " minute to second");
+ break;
+ case INTERVAL_FULL_RANGE:
+ // Nothing
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (list_length(type_name->typmods) == 2)
+ {
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
+ if (precision != INTERVAL_FULL_PRECISION)
+ appendStringInfo(str, "(%d)", precision);
+ }
+
+ skip_typmods = true;
+ }
+ else
+ {
+ appendStringInfoString(str, "pg_catalog.");
+ appendStringInfoString(str, name);
+ }
+ }
+ else
+ {
+ deparseAnyName(str, type_name->names);
+ }
+
+ if (list_length(type_name->typmods) > 0 && !skip_typmods)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ if (IsA(lfirst(lc), A_Const))
+ deparseAConst(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ParamRef))
+ deparseParamRef(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ColumnRef))
+ deparseColumnRef(str, lfirst(lc));
+ else
+ Assert(false);
+
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ foreach(lc, type_name->arrayBounds)
+ {
+ appendStringInfoChar(str, '[');
+ if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
+ deparseSignedIconst(str, lfirst(lc));
+ appendStringInfoChar(str, ']');
+ }
+
+ if (type_name->pct_type)
+ appendStringInfoString(str, "%type");
+}
+
+static void deparseNullTest(StringInfo str, NullTest *null_test)
+{
+ // argisrow is always false in raw parser output
+ Assert(null_test->argisrow == false);
+
+ deparseExpr(str, (Node *) null_test->arg);
+ switch (null_test->nulltesttype)
+ {
+ case IS_NULL:
+ appendStringInfoString(str, " IS NULL");
+ break;
+ case IS_NOT_NULL:
+ appendStringInfoString(str, " IS NOT NULL");
+ break;
+ }
+}
+
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CASE ");
+
+ if (case_expr->arg != NULL)
+ {
+ deparseExpr(str, (Node *) case_expr->arg);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, case_expr->args)
+ {
+ deparseCaseWhen(str, castNode(CaseWhen, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (case_expr->defresult != NULL)
+ {
+ appendStringInfoString(str, "ELSE ");
+ deparseExpr(str, (Node *) case_expr->defresult);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "END");
+}
+
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when)
+{
+ appendStringInfoString(str, "WHEN ");
+ deparseExpr(str, (Node *) case_when->expr);
+ appendStringInfoString(str, " THEN ");
+ deparseExpr(str, (Node *) case_when->result);
+}
+
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection)
+{
+ ListCell *lc;
+ bool need_parens =
+ IsA(a_indirection->arg, A_Indirection) ||
+ IsA(a_indirection->arg, FuncCall) ||
+ IsA(a_indirection->arg, A_Expr) ||
+ IsA(a_indirection->arg, TypeCast) ||
+ IsA(a_indirection->arg, RowExpr) ||
+ (IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices));
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, a_indirection->arg);
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ deparseOptIndirection(str, a_indirection->indirection, 0);
+}
+
+static void deparseAIndices(StringInfo str, A_Indices *a_indices)
+{
+ appendStringInfoChar(str, '[');
+ if (a_indices->lidx != NULL)
+ deparseExpr(str, a_indices->lidx);
+ if (a_indices->is_slice)
+ appendStringInfoChar(str, ':');
+ if (a_indices->uidx != NULL)
+ deparseExpr(str, a_indices->uidx);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr)
+{
+ appendStringInfoString(str, "COALESCE(");
+ deparseExprList(str, coalesce_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr)
+{
+ switch (min_max_expr->op)
+ {
+ case IS_GREATEST:
+ appendStringInfoString(str, "GREATEST(");
+ break;
+ case IS_LEAST:
+ appendStringInfoString(str, "LEAST(");
+ break;
+ }
+ deparseExprList(str, min_max_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test)
+{
+ deparseExpr(str, (Node *) boolean_test->arg);
+ switch (boolean_test->booltesttype)
+ {
+ case IS_TRUE:
+ appendStringInfoString(str, " IS TRUE");
+ break;
+ case IS_NOT_TRUE:
+ appendStringInfoString(str, " IS NOT TRUE");
+ break;
+ case IS_FALSE:
+ appendStringInfoString(str, " IS FALSE");
+ break;
+ case IS_NOT_FALSE:
+ appendStringInfoString(str, " IS NOT FALSE");
+ break;
+ case IS_UNKNOWN:
+ appendStringInfoString(str, " IS UNKNOWN");
+ break;
+ case IS_NOT_UNKNOWN:
+ appendStringInfoString(str, " IS NOT UNKNOWN");
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
+{
+ ListCell *lc;
+
+ if (column_def->colname != NULL)
+ {
+ appendStringInfoString(str, column_def->colname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->typeName != NULL)
+ {
+ deparseTypeName(str, column_def->typeName);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->raw_default != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseExpr(str, column_def->raw_default);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->fdwoptions != NULL)
+ {
+ deparseCreateGenericOptions(str, column_def->fdwoptions);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, column_def->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->collClause != NULL)
+ {
+ deparseCollateClause(str, column_def->collClause);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (insert_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, insert_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "INSERT INTO ");
+ deparseRangeVar(str, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(insert_stmt->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseInsertColumnList(str, insert_stmt->cols);
+ appendStringInfoString(str, ") ");
+ }
+
+ switch (insert_stmt->override)
+ {
+ case OVERRIDING_NOT_SET:
+ // Do nothing
+ break;
+ case OVERRIDING_USER_VALUE:
+ appendStringInfoString(str, "OVERRIDING USER VALUE ");
+ break;
+ case OVERRIDING_SYSTEM_VALUE:
+ appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
+ break;
+ }
+
+ if (insert_stmt->selectStmt != NULL)
+ {
+ deparseSelectStmt(str, castNode(SelectStmt, insert_stmt->selectStmt));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "DEFAULT VALUES ");
+ }
+
+ if (insert_stmt->onConflictClause != NULL)
+ {
+ deparseOnConflictClause(str, insert_stmt->onConflictClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(insert_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, insert_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInferClause(StringInfo str, InferClause *infer_clause)
+{
+ ListCell *lc;
+
+ if (list_length(infer_clause->indexElems) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, infer_clause->indexElems)
+ {
+ deparseIndexElem(str, lfirst(lc));
+ if (lnext(infer_clause->indexElems, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ if (infer_clause->conname != NULL)
+ {
+ appendStringInfoString(str, "ON CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(infer_clause->conname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, infer_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ON CONFLICT ");
+
+ if (on_conflict_clause->infer != NULL)
+ {
+ deparseInferClause(str, on_conflict_clause->infer);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (on_conflict_clause->action)
+ {
+ case ONCONFLICT_NONE:
+ Assert(false);
+ break;
+ case ONCONFLICT_NOTHING:
+ appendStringInfoString(str, "DO NOTHING ");
+ break;
+ case ONCONFLICT_UPDATE:
+ appendStringInfoString(str, "DO UPDATE ");
+ break;
+ }
+
+ if (list_length(on_conflict_clause->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, on_conflict_clause->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, on_conflict_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
+{
+ ListCell* lc;
+ ListCell* lc2;
+ ListCell* lc3;
+
+ if (update_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, update_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "UPDATE ");
+ deparseRangeVar(str, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(update_stmt->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, update_stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, update_stmt->fromClause);
+ deparseWhereClause(str, update_stmt->whereClause);
+
+ if (list_length(update_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, update_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
+{
+ if (delete_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, delete_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "DELETE FROM ");
+ deparseRangeVar(str, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (delete_stmt->usingClause != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseFromList(str, delete_stmt->usingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, delete_stmt->whereClause);
+
+ if (list_length(delete_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, delete_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause)
+{
+ ListCell *lc;
+
+ switch (locking_clause->strength)
+ {
+ case LCS_NONE:
+ /* no such clause - only used in PlanRowMark */
+ Assert(false);
+ break;
+ case LCS_FORKEYSHARE:
+ appendStringInfoString(str, "FOR KEY SHARE ");
+ break;
+ case LCS_FORSHARE:
+ appendStringInfoString(str, "FOR SHARE ");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ appendStringInfoString(str, "FOR NO KEY UPDATE ");
+ break;
+ case LCS_FORUPDATE:
+ appendStringInfoString(str, "FOR UPDATE ");
+ break;
+ }
+
+ if (list_length(locking_clause->lockedRels) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseQualifiedNameList(str, locking_clause->lockedRels);
+ }
+
+ switch (locking_clause->waitPolicy)
+ {
+ case LockWaitError:
+ appendStringInfoString(str, "NOWAIT");
+ break;
+ case LockWaitSkip:
+ appendStringInfoString(str, "SKIP LOCKED");
+ break;
+ case LockWaitBlock:
+ // Default
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default)
+{
+ appendStringInfoString(str, "DEFAULT");
+}
+
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ appendStringInfoString(str, "CREATE CAST (");
+ deparseTypeName(str, create_cast_stmt->sourcetype);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, create_cast_stmt->targettype);
+ appendStringInfoString(str, ") ");
+
+ if (create_cast_stmt->func != NULL)
+ {
+ appendStringInfoString(str, "WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_cast_stmt->func);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_cast_stmt->inout)
+ {
+ appendStringInfoString(str, "WITH INOUT ");
+ }
+ else
+ {
+ appendStringInfoString(str, "WITHOUT FUNCTION ");
+ }
+
+ switch (create_cast_stmt->context)
+ {
+ case COERCION_IMPLICIT:
+ appendStringInfoString(str, "AS IMPLICIT");
+ break;
+ case COERCION_ASSIGNMENT:
+ appendStringInfoString(str, "AS ASSIGNMENT");
+ break;
+ case COERCION_EXPLICIT:
+ // Default
+ break;
+ }
+}
+
+static void deparseCreateOpClassStmt(StringInfo str, CreateOpClassStmt *create_op_class_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE OPERATOR CLASS ");
+
+ deparseAnyName(str, create_op_class_stmt->opclassname);
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->isDefault)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, create_op_class_stmt->datatype);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_class_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->opfamilyname != NULL)
+ {
+ appendStringInfoString(str, "FAMILY ");
+ deparseAnyName(str, create_op_class_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "AS ");
+ deparseOpclassItemList(str, create_op_class_stmt->items);
+}
+
+static void deparseCreateOpFamilyStmt(StringInfo str, CreateOpFamilyStmt *create_op_family_stmt)
+{
+ appendStringInfoString(str, "CREATE OPERATOR FAMILY ");
+
+ deparseAnyName(str, create_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_family_stmt->amname));
+}
+
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item)
+{
+ ListCell *lc = NULL;
+
+ switch (create_op_class_item->itemtype)
+ {
+ case OPCLASS_ITEM_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+
+ if (create_op_class_item->name != NULL)
+ {
+ if (create_op_class_item->name->objargs != NULL)
+ deparseOperatorWithArgtypes(str, create_op_class_item->name);
+ else
+ deparseAnyOperator(str, create_op_class_item->name->objname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_op_class_item->order_family != NULL)
+ {
+ appendStringInfoString(str, "FOR ORDER BY ");
+ deparseAnyName(str, create_op_class_item->order_family);
+ }
+
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoChar(str, ')');
+ }
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoString(str, ") ");
+ }
+ if (create_op_class_item->name != NULL)
+ deparseFunctionWithArgtypes(str, create_op_class_item->name);
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_STORAGETYPE:
+ appendStringInfoString(str, "STORAGE ");
+ deparseTypeName(str, create_op_class_item->storedtype);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseTableLikeClause(StringInfo str, TableLikeClause *table_like_clause)
+{
+ appendStringInfoString(str, "LIKE ");
+ deparseRangeVar(str, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
+ appendStringInfoString(str, "INCLUDING ALL ");
+ else
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+ appendStringInfoString(str, "INCLUDING COMMENTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ appendStringInfoString(str, "INCLUDING CONSTRAINTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
+ appendStringInfoString(str, "INCLUDING DEFAULTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
+ appendStringInfoString(str, "INCLUDING IDENTITY ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED)
+ appendStringInfoString(str, "INCLUDING GENERATED ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ appendStringInfoString(str, "INCLUDING INDEXES ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
+ appendStringInfoString(str, "INCLUDING STATISTICS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ appendStringInfoString(str, "INCLUDING STORAGE ");
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt)
+{
+ ListCell *lc;
+
+ Assert(create_domain_stmt->typeName != NULL);
+
+ appendStringInfoString(str, "CREATE DOMAIN ");
+ deparseAnyName(str, create_domain_stmt->domainname);
+ appendStringInfoString(str, " AS ");
+
+ deparseTypeName(str, create_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (create_domain_stmt->collClause != NULL)
+ {
+ deparseCollateClause(str, create_domain_stmt->collClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_domain_stmt->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateExtensionStmt(StringInfo str, CreateExtensionStmt *create_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE EXTENSION ");
+
+ if (create_extension_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseColId(str, create_extension_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, create_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "schema") == 0)
+ {
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "cascade") == 0)
+ {
+ appendStringInfoString(str, "CASCADE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraint(StringInfo str, Constraint *constraint)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, constraint->conname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (constraint->contype) {
+ case CONSTR_NULL:
+ appendStringInfoString(str, "NULL ");
+ break;
+ case CONSTR_NOTNULL:
+ appendStringInfoString(str, "NOT NULL ");
+ break;
+ case CONSTR_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, constraint->raw_expr);
+ break;
+ case CONSTR_IDENTITY:
+ appendStringInfoString(str, "GENERATED ");
+ switch (constraint->generated_when)
+ {
+ case ATTRIBUTE_IDENTITY_ALWAYS:
+ appendStringInfoString(str, "ALWAYS ");
+ break;
+ case ATTRIBUTE_IDENTITY_BY_DEFAULT:
+ appendStringInfoString(str, "BY DEFAULT ");
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoString(str, "AS IDENTITY ");
+ deparseOptParenthesizedSeqOptList(str, constraint->options);
+ break;
+ case CONSTR_GENERATED:
+ Assert(constraint->generated_when == ATTRIBUTE_IDENTITY_ALWAYS);
+ appendStringInfoString(str, "GENERATED ALWAYS AS (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") STORED ");
+ break;
+ case CONSTR_CHECK:
+ appendStringInfoString(str, "CHECK (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") ");
+ break;
+ case CONSTR_PRIMARY:
+ appendStringInfoString(str, "PRIMARY KEY ");
+ break;
+ case CONSTR_UNIQUE:
+ appendStringInfoString(str, "UNIQUE ");
+ break;
+ case CONSTR_EXCLUSION:
+ appendStringInfoString(str, "EXCLUDE ");
+ if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(constraint->access_method));
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoChar(str, '(');
+ foreach(lc, constraint->exclusions)
+ {
+ List *exclusion = castNode(List, lfirst(lc));
+ Assert(list_length(exclusion) == 2);
+ deparseIndexElem(str, castNode(IndexElem, linitial(exclusion)));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyOperator(str, castNode(List, lsecond(exclusion)));
+ if (lnext(constraint->exclusions, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ if (constraint->where_clause != NULL)
+ {
+ appendStringInfoString(str, "WHERE (");
+ deparseExpr(str, constraint->where_clause);
+ appendStringInfoString(str, ") ");
+ }
+ break;
+ case CONSTR_FOREIGN:
+ if (list_length(constraint->fk_attrs) > 0)
+ appendStringInfoString(str, "FOREIGN KEY ");
+ break;
+ case CONSTR_ATTR_DEFERRABLE:
+ appendStringInfoString(str, "DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ appendStringInfoString(str, "NOT DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_DEFERRED:
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+ break;
+ case CONSTR_ATTR_IMMEDIATE:
+ appendStringInfoString(str, "INITIALLY IMMEDIATE ");
+ break;
+ }
+
+ if (list_length(constraint->keys) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->keys);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (list_length(constraint->fk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->fk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->pktable != NULL)
+ {
+ appendStringInfoString(str, "REFERENCES ");
+ deparseRangeVar(str, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ if (list_length(constraint->pk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->pk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ switch (constraint->fk_matchtype)
+ {
+ case FKCONSTR_MATCH_SIMPLE:
+ // Default
+ break;
+ case FKCONSTR_MATCH_FULL:
+ appendStringInfoString(str, "MATCH FULL ");
+ break;
+ case FKCONSTR_MATCH_PARTIAL:
+ // Not implemented in Postgres
+ Assert(false);
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_upd_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON UPDATE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON UPDATE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON UPDATE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON UPDATE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_del_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON DELETE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON DELETE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON DELETE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON DELETE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ if (list_length(constraint->including) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ deparseColumnList(str, constraint->including);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->indexname != NULL)
+ appendStringInfo(str, "USING INDEX %s ", quote_identifier(constraint->indexname));
+
+ if (constraint->indexspace != NULL)
+ appendStringInfo(str, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
+
+ if (constraint->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (constraint->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (constraint->is_no_inherit)
+ appendStringInfoString(str, "NO INHERIT ");
+
+ if (constraint->skip_validation)
+ appendStringInfoString(str, "NOT VALID ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
+{
+ ListCell *lc;
+ bool tableFunc = false;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_function_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_function_stmt->is_procedure)
+ appendStringInfoString(str, "PROCEDURE ");
+ else
+ appendStringInfoString(str, "FUNCTION ");
+
+ deparseFuncName(str, create_function_stmt->funcname);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode != FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc) && castNode(FunctionParameter, lfirst(lnext(create_function_stmt->parameters, lc)))->mode != FUNC_PARAM_TABLE)
+ appendStringInfoString(str, ", ");
+ }
+ else
+ {
+ tableFunc = true;
+ }
+ }
+ appendStringInfoString(str, ") ");
+
+ if (tableFunc)
+ {
+ appendStringInfoString(str, "RETURNS TABLE (");
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode == FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_function_stmt->returnType != NULL)
+ {
+ appendStringInfoString(str, "RETURNS ");
+ deparseTypeName(str, create_function_stmt->returnType);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_function_stmt->options)
+ {
+ deparseCreateFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter)
+{
+ switch (function_parameter->mode)
+ {
+ case FUNC_PARAM_IN: /* input only */
+ // Default
+ break;
+ case FUNC_PARAM_OUT: /* output only */
+ appendStringInfoString(str, "OUT ");
+ break;
+ case FUNC_PARAM_INOUT: /* both */
+ appendStringInfoString(str, "INOUT ");
+ break;
+ case FUNC_PARAM_VARIADIC: /* variadic (always input) */
+ appendStringInfoString(str, "VARIADIC ");
+ break;
+ case FUNC_PARAM_TABLE: /* table function output column */
+ // No special annotation, the caller is expected to correctly put
+ // this into the RETURNS part of the CREATE FUNCTION statement
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (function_parameter->name != NULL)
+ {
+ appendStringInfoString(str, function_parameter->name);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseTypeName(str, function_parameter->argType);
+ appendStringInfoChar(str, ' ');
+
+ if (function_parameter->defexpr != NULL)
+ {
+ appendStringInfoString(str, "= ");
+ deparseExpr(str, function_parameter->defexpr);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_stmt)
+{
+ appendStringInfoString(str, "CHECKPOINT");
+}
+
+static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SCHEMA ");
+
+ if (create_schema_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (create_schema_stmt->schemaname)
+ {
+ deparseColId(str, create_schema_stmt->schemaname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->authrole != NULL)
+ {
+ appendStringInfoString(str, "AUTHORIZATION ");
+ deparseRoleSpec(str, create_schema_stmt->authrole);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_schema_stmt->schemaElts)
+ {
+ deparseSchemaStmt(str, lfirst(lc));
+ if (lnext(create_schema_stmt->schemaElts, lc))
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleSetStmt(StringInfo str, AlterRoleSetStmt *alter_role_set_stmt)
+{
+ appendStringInfoString(str, "ALTER ROLE ");
+
+ if (alter_role_set_stmt->role == NULL)
+ appendStringInfoString(str, "ALL");
+ else
+ deparseRoleSpec(str, alter_role_set_stmt->role);
+
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_set_stmt->database != NULL)
+ {
+ appendStringInfoString(str, "IN DATABASE ");
+ appendStringInfoString(str, quote_identifier(alter_role_set_stmt->database));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseVariableSetStmt(str, alter_role_set_stmt->setstmt);
+}
+
+static void deparseCreateConversionStmt(StringInfo str, CreateConversionStmt *create_conversion_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_conversion_stmt->def)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, create_conversion_stmt->conversion_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "FOR ");
+ deparseStringLiteral(str, create_conversion_stmt->for_encoding_name);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, create_conversion_stmt->to_encoding_name);
+
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, create_conversion_stmt->func_name);
+}
+
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
+{
+ switch (role_spec->roletype)
+ {
+ case ROLESPEC_CSTRING:
+ Assert(role_spec->rolename != NULL);
+ appendStringInfoString(str, quote_identifier(role_spec->rolename));
+ break;
+ case ROLESPEC_CURRENT_USER:
+ appendStringInfoString(str, "CURRENT_USER");
+ break;
+ case ROLESPEC_SESSION_USER:
+ appendStringInfoString(str, "SESSION_USER");
+ break;
+ case ROLESPEC_PUBLIC:
+ appendStringInfoString(str, "public");
+ break;
+ }
+}
+
+// "part_elem" in gram.y
+static void deparsePartitionElem(StringInfo str, PartitionElem *partition_elem)
+{
+ ListCell *lc;
+
+ if (partition_elem->name != NULL)
+ {
+ deparseColId(str, partition_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (partition_elem->expr != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, partition_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptCollate(str, partition_elem->collation);
+ deparseAnyName(str, partition_elem->opclass);
+
+ removeTrailingSpace(str);
+}
+
+static void deparsePartitionSpec(StringInfo str, PartitionSpec *partition_spec)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "PARTITION BY ");
+ appendStringInfoString(str, partition_spec->strategy);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, partition_spec->partParams)
+ {
+ deparsePartitionElem(str, castNode(PartitionElem, lfirst(lc)));
+ if (lnext(partition_spec->partParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparsePartitionBoundSpec(StringInfo str, PartitionBoundSpec *partition_bound_spec)
+{
+ ListCell *lc;
+
+ if (partition_bound_spec->is_default)
+ {
+ appendStringInfoString(str, "DEFAULT");
+ return;
+ }
+
+ appendStringInfoString(str, "FOR VALUES ");
+
+ switch (partition_bound_spec->strategy)
+ {
+ case PARTITION_STRATEGY_HASH:
+ appendStringInfo(str, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
+ break;
+ case PARTITION_STRATEGY_LIST:
+ appendStringInfoString(str, "IN (");
+ deparseExprList(str, partition_bound_spec->listdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ appendStringInfoString(str, "FROM (");
+ deparseExprList(str, partition_bound_spec->lowerdatums);
+ appendStringInfoString(str, ") TO (");
+ deparseExprList(str, partition_bound_spec->upperdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
+{
+ deparseRangeVar(str, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (partition_cmd->bound != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparsePartitionBoundSpec(str, partition_cmd->bound);
+ }
+}
+
+// "TableElement" in gram.y
+static void deparseTableElement(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnDef:
+ deparseColumnDef(str, castNode(ColumnDef, node));
+ break;
+ case T_TableLikeClause:
+ deparseTableLikeClause(str, castNode(TableLikeClause, node));
+ break;
+ case T_Constraint:
+ deparseConstraint(str, castNode(Constraint, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseCreateStmt(StringInfo str, CreateStmt *create_stmt, bool is_foreign_table)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (is_foreign_table)
+ appendStringInfoString(str, "FOREIGN ");
+
+ deparseOptTemp(str, create_stmt->relation->relpersistence);
+
+ appendStringInfoString(str, "TABLE ");
+
+ if (create_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_stmt->ofTypename != NULL)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseTypeName(str, create_stmt->ofTypename);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ Assert(list_length(create_stmt->inhRelations) == 1);
+ appendStringInfoString(str, "PARTITION OF ");
+ deparseRangeVar(str, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(create_stmt->tableElts) > 0)
+ {
+ // In raw parse output tableElts contains both columns and constraints
+ // (and the constraints field is NIL)
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_stmt->tableElts)
+ {
+ deparseTableElement(str, lfirst(lc));
+ if (lnext(create_stmt->tableElts, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
+ {
+ appendStringInfoString(str, "() ");
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ deparsePartitionBoundSpec(str, create_stmt->partbound);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ deparseOptInherit(str, create_stmt->inhRelations);
+ }
+
+ if (create_stmt->partspec != NULL)
+ {
+ deparsePartitionSpec(str, create_stmt->partspec);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_stmt->accessMethod));
+ }
+
+ deparseOptWith(str, create_stmt->options);
+
+ switch (create_stmt->oncommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No ON COMMIT clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (create_stmt->tablespacename != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(create_stmt->tablespacename));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFdwStmt(StringInfo str, CreateFdwStmt *create_fdw_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, create_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseCreateGenericOptions(str, create_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFdwStmt(StringInfo str, AlterFdwStmt *alter_fdw_stmt)
+{
+ appendStringInfoString(str, "ALTER FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(alter_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, alter_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_fdw_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateForeignServerStmt(StringInfo str, CreateForeignServerStmt *create_foreign_server_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SERVER ");
+ if (create_foreign_server_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (create_foreign_server_stmt->servertype != NULL)
+ {
+ appendStringInfoString(str, "TYPE ");
+ deparseStringLiteral(str, create_foreign_server_stmt->servertype);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_foreign_server_stmt->version != NULL)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseStringLiteral(str, create_foreign_server_stmt->version);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterForeignServerStmt(StringInfo str, AlterForeignServerStmt *alter_foreign_server_stmt)
+{
+ appendStringInfoString(str, "ALTER SERVER ");
+
+ appendStringInfoString(str, quote_identifier(alter_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_foreign_server_stmt->has_version)
+ {
+ appendStringInfoString(str, "VERSION ");
+ if (alter_foreign_server_stmt->version != NULL)
+ deparseStringLiteral(str, alter_foreign_server_stmt->version);
+ else
+ appendStringInfoString(str, "NULL");
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_foreign_server_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateUserMappingStmt(StringInfo str, CreateUserMappingStmt *create_user_mapping_stmt)
+{
+ appendStringInfoString(str, "CREATE USER MAPPING ");
+ if (create_user_mapping_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, create_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(create_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreatedbStmt(StringInfo str, CreatedbStmt *createdb_stmt)
+{
+ appendStringInfoString(str, "CREATE DATABASE ");
+ deparseColId(str, createdb_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, createdb_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterUserMappingStmt(StringInfo str, AlterUserMappingStmt *alter_user_mapping_stmt)
+{
+ appendStringInfoString(str, "ALTER USER MAPPING FOR ");
+ deparseRoleSpec(str, alter_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(alter_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseAlterGenericOptions(str, alter_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropUserMappingStmt(StringInfo str, DropUserMappingStmt *drop_user_mapping_stmt)
+{
+ appendStringInfoString(str, "DROP USER MAPPING ");
+
+ if (drop_user_mapping_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, drop_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(drop_user_mapping_stmt->servername));
+}
+
+static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "SECURITY LABEL ");
+
+ if (sec_label_stmt->provider != NULL)
+ {
+ appendStringInfoString(str, "FOR ");
+ appendStringInfoString(str, quote_identifier(sec_label_stmt->provider));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ switch (sec_label_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseValue(str, (Value *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ default:
+ // Not supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (sec_label_stmt->label != NULL)
+ deparseStringLiteral(str, sec_label_stmt->label);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateForeignTableStmt(StringInfo str, CreateForeignTableStmt *create_foreign_table_stmt)
+{
+ ListCell *lc;
+
+ deparseCreateStmt(str, &create_foreign_table_stmt->base, true);
+
+ appendStringInfoString(str, " SERVER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_table_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_foreign_table_stmt->options) > 0)
+ deparseAlterGenericOptions(str, create_foreign_table_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseImportForeignSchemaStmt(StringInfo str, ImportForeignSchemaStmt *import_foreign_schema_stmt)
+{
+ appendStringInfoString(str, "IMPORT FOREIGN SCHEMA ");
+
+ appendStringInfoString(str, import_foreign_schema_stmt->remote_schema);
+ appendStringInfoChar(str, ' ');
+
+ switch (import_foreign_schema_stmt->list_type)
+ {
+ case FDW_IMPORT_SCHEMA_ALL:
+ // Default
+ break;
+ case FDW_IMPORT_SCHEMA_LIMIT_TO:
+ appendStringInfoString(str, "LIMIT TO (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ case FDW_IMPORT_SCHEMA_EXCEPT:
+ appendStringInfoString(str, "EXCEPT (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ }
+
+ appendStringInfoString(str, "FROM SERVER ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->server_name));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "INTO ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->local_schema));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, import_foreign_schema_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_table_as_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
+
+ switch (create_table_as_stmt->relkind)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ if (create_table_as_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseIntoClause(str, create_table_as_stmt->into);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ if (IsA(create_table_as_stmt->query, ExecuteStmt))
+ deparseExecuteStmt(str, castNode(ExecuteStmt, create_table_as_stmt->query));
+ else
+ deparseSelectStmt(str, castNode(SelectStmt, create_table_as_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_as_stmt->into->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (view_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ deparseOptTemp(str, view_stmt->view->relpersistence);
+
+ appendStringInfoString(str, "VIEW ");
+ deparseRangeVar(str, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(view_stmt->aliases) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, view_stmt->aliases);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, view_stmt->options);
+
+ appendStringInfoString(str, "AS ");
+ deparseSelectStmt(str, castNode(SelectStmt, view_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ switch (view_stmt->withCheckOption)
+ {
+ case NO_CHECK_OPTION:
+ // Default
+ break;
+ case LOCAL_CHECK_OPTION:
+ appendStringInfoString(str, "WITH LOCAL CHECK OPTION ");
+ break;
+ case CASCADED_CHECK_OPTION:
+ appendStringInfoString(str, "WITH CHECK OPTION ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "DROP ");
+
+ switch (drop_stmt->removeType)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ default:
+ // Other object types are not supported here in the parser
+ Assert(false);
+ }
+
+ if (drop_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (drop_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (drop_stmt->removeType)
+ {
+ // drop_type_any_name
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ deparseAnyNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name_on_any_name
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseColId(str, strVal(llast(l)));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_CAST:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TRANSFORM:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_LANGUAGE:
+ deparseStringLiteral(str, strVal(linitial(drop_stmt->objects)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_AGGREGATE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPERATOR:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseOptDropBehavior(str, drop_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set)
+{
+ switch(grouping_set->kind)
+ {
+ case GROUPING_SET_EMPTY:
+ appendStringInfoString(str, "()");
+ break;
+ case GROUPING_SET_SIMPLE:
+ // Not present in raw parse trees
+ Assert(false);
+ break;
+ case GROUPING_SET_ROLLUP:
+ appendStringInfoString(str, "ROLLUP (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_CUBE:
+ appendStringInfoString(str, "CUBE (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_SETS:
+ appendStringInfoString(str, "GROUPING SETS (");
+ deparseGroupByList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ }
+}
+
+static void deparseDropTableSpaceStmt(StringInfo str, DropTableSpaceStmt *drop_table_space_stmt)
+{
+ appendStringInfoString(str, "DROP TABLESPACE ");
+
+ if (drop_table_space_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_table_space_stmt->tablespacename);
+}
+
+static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt *alter_object_depends_stmt)
+{
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_depends_stmt->objectType)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ deparseColId(str, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ // No other object types supported here
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (alter_object_depends_stmt->remove)
+ appendStringInfoString(str, "NO ");
+
+ appendStringInfoString(str, "DEPENDS ON EXTENSION ");
+ deparseColId(str, strVal(alter_object_depends_stmt->extname));
+}
+
+static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
+{
+ List *l = NULL;
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_schema_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ appendStringInfoString(str, quote_identifier(strVal(alter_object_schema_stmt->object)));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " SET SCHEMA ");
+ appendStringInfoString(str, quote_identifier(alter_object_schema_stmt->newschema));
+}
+
+static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+ const char *options = NULL;
+ bool trailing_missing_ok = false;
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AddColumn: /* add column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ADD ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ADD COLUMN ");
+ break;
+ case AT_AddColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_ColumnDefault: /* alter column default */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ if (alter_table_cmd->def != NULL)
+ options = "SET DEFAULT";
+ else
+ options = "DROP DEFAULT";
+ break;
+ case AT_CookedColumnDefault: /* add a pre-cooked column default */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropNotNull: /* alter column drop not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP NOT NULL";
+ break;
+ case AT_SetNotNull: /* alter column set not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET NOT NULL";
+ break;
+ case AT_DropExpression: /* alter column drop expression */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP EXPRESSION";
+ trailing_missing_ok = true;
+ break;
+ case AT_CheckNotNull: /* check column is already marked not null */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_SetStatistics: /* alter column set statistics */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STATISTICS";
+ break;
+ case AT_SetOptions: /* alter column set ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET";
+ break;
+ case AT_ResetOptions: /* alter column reset ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "RESET";
+ break;
+ case AT_SetStorage: /* alter column set storage */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STORAGE";
+ break;
+ case AT_DropColumn: /* drop column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "DROP ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "DROP ");
+ break;
+ case AT_DropColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndex: /* add index */
+ appendStringInfoString(str, "ADD INDEX ");
+ break;
+ case AT_ReAddIndex: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddConstraint: /* add constraint */
+ appendStringInfoString(str, "ADD ");
+ break;
+ case AT_AddConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterConstraint: /* alter constraint */
+ appendStringInfoString(str, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
+ break;
+ case AT_ValidateConstraint: /* validate constraint */
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ break;
+ case AT_ValidateConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndexConstraint: /* add constraint using existing index */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropConstraint: /* drop constraint */
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ break;
+ case AT_DropConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddComment: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterColumnType: /* alter column type */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ALTER ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "TYPE";
+ break;
+ case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ // Handled via special case in def handling
+ break;
+ case AT_ChangeOwner: /* change owner */
+ appendStringInfoString(str, "OWNER TO ");
+ deparseRoleSpec(str, alter_table_cmd->newowner);
+ break;
+ case AT_ClusterOn: /* CLUSTER ON */
+ appendStringInfoString(str, "CLUSTER ON ");
+ break;
+ case AT_DropCluster: /* SET WITHOUT CLUSTER */
+ appendStringInfoString(str, "SET WITHOUT CLUSTER ");
+ break;
+ case AT_SetLogged: /* SET LOGGED */
+ appendStringInfoString(str, "SET LOGGED ");
+ break;
+ case AT_SetUnLogged: /* SET UNLOGGED */
+ appendStringInfoString(str, "SET UNLOGGED ");
+ break;
+ case AT_DropOids: /* SET WITHOUT OIDS */
+ appendStringInfoString(str, "SET WITHOUT OIDS ");
+ break;
+ case AT_SetTableSpace: /* SET TABLESPACE */
+ appendStringInfoString(str, "SET TABLESPACE ");
+ break;
+ case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
+ appendStringInfoString(str, "SET ");
+ break;
+ case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
+ appendStringInfoString(str, "RESET ");
+ break;
+ case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_EnableTrig: /* ENABLE TRIGGER name */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
+ appendStringInfoString(str, "ENABLE ALWAYS TRIGGER ");
+ break;
+ case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
+ appendStringInfoString(str, "ENABLE REPLICA TRIGGER ");
+ break;
+ case AT_DisableTrig: /* DISABLE TRIGGER name */
+ appendStringInfoString(str, "DISABLE TRIGGER ");
+ break;
+ case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
+ appendStringInfoString(str, "DISABLE TRIGGER ALL ");
+ break;
+ case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
+ appendStringInfoString(str, "ENABLE TRIGGER USER ");
+ break;
+ case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
+ appendStringInfoString(str, "DISABLE TRIGGER USER ");
+ break;
+ case AT_EnableRule: /* ENABLE RULE name */
+ appendStringInfoString(str, "ENABLE RULE ");
+ break;
+ case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
+ appendStringInfoString(str, "ENABLE ALWAYS RULE ");
+ break;
+ case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
+ appendStringInfoString(str, "ENABLE REPLICA RULE ");
+ break;
+ case AT_DisableRule: /* DISABLE RULE name */
+ appendStringInfoString(str, "DISABLE RULE ");
+ break;
+ case AT_AddInherit: /* INHERIT parent */
+ appendStringInfoString(str, "INHERIT ");
+ break;
+ case AT_DropInherit: /* NO INHERIT parent */
+ appendStringInfoString(str, "NO INHERIT ");
+ break;
+ case AT_AddOf: /* OF */
+ appendStringInfoString(str, "OF ");
+ break;
+ case AT_DropOf: /* NOT OF */
+ appendStringInfoString(str, "NOT OF ");
+ break;
+ case AT_ReplicaIdentity: /* REPLICA IDENTITY */
+ appendStringInfoString(str, "REPLICA IDENTITY ");
+ break;
+ case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
+ appendStringInfoString(str, "ENABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
+ appendStringInfoString(str, "DISABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
+ appendStringInfoString(str, "FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
+ appendStringInfoString(str, "NO FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_GenericOptions: /* OPTIONS (...) */
+ // Handled in def field handling
+ break;
+ case AT_AttachPartition: /* ATTACH PARTITION */
+ appendStringInfoString(str, "ATTACH PARTITION ");
+ break;
+ case AT_DetachPartition: /* DETACH PARTITION */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_AddIdentity: /* ADD IDENTITY */
+ appendStringInfoString(str, "ALTER ");
+ options = "ADD";
+ // Other details are output via the constraint node (in def field)
+ break;
+ case AT_SetIdentity: /* SET identity column options */
+ appendStringInfoString(str, "ALTER ");
+ break;
+ case AT_DropIdentity: /* DROP IDENTITY */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP IDENTITY";
+ trailing_missing_ok = true;
+ break;
+ }
+
+ if (alter_table_cmd->missing_ok && !trailing_missing_ok)
+ {
+ if (alter_table_cmd->subtype == AT_AddColumn)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ else
+ appendStringInfoString(str, "IF EXISTS ");
+ }
+
+ if (alter_table_cmd->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(alter_table_cmd->name));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->num > 0)
+ appendStringInfo(str, "%d ", alter_table_cmd->num);
+
+ if (options != NULL)
+ {
+ appendStringInfoString(str, options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->missing_ok && trailing_missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddColumn:
+ case AT_AlterColumnType:
+ deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ColumnDefault:
+ if (alter_table_cmd->def != NULL)
+ {
+ deparseExpr(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case AT_SetStatistics:
+ deparseSignedIconst(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetOptions:
+ case AT_ResetOptions:
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+ deparseRelOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetStorage:
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddIdentity:
+ case AT_AddConstraint:
+ case AT_AlterConstraint:
+ deparseConstraint(str, castNode(Constraint, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetIdentity:
+ deparseAlterIdentityColumnOptionList(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AlterColumnGenericOptions:
+ case AT_GenericOptions:
+ deparseAlterGenericOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddInherit:
+ case AT_DropInherit:
+ deparseRangeVar(str, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddOf:
+ deparseTypeName(str, castNode(TypeName, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ReplicaIdentity:
+ deparseReplicaIdentityStmt(str, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(alter_table_cmd->def == NULL);
+ break;
+ }
+
+ deparseOptDropBehavior(str, alter_table_cmd->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
+{
+ ListCell *lc;
+ DeparseNodeContext context = DEPARSE_NODE_CONTEXT_NONE;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_table_stmt->relkind)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ context = DEPARSE_NODE_CONTEXT_ALTER_TYPE;
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (alter_table_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_table_stmt->relation, context);
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, alter_table_stmt->cmds)
+ {
+ deparseAlterTableCmd(str, castNode(AlterTableCmd, lfirst(lc)), context);
+ if (lnext(alter_table_stmt->cmds, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterTableSpaceOptionsStmt(StringInfo str, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
+{
+ appendStringInfoString(str, "ALTER TABLESPACE ");
+ deparseColId(str, alter_table_space_options_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_table_space_options_stmt->isReset)
+ appendStringInfoString(str, "RESET ");
+ else
+ appendStringInfoString(str, "SET ");
+
+ deparseRelOptions(str, alter_table_space_options_stmt->options);
+}
+
+static void deparseAlterDomainStmt(StringInfo str, AlterDomainStmt *alter_domain_stmt)
+{
+ appendStringInfoString(str, "ALTER DOMAIN ");
+ deparseAnyName(str, alter_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_domain_stmt->subtype)
+ {
+ case 'T':
+ if (alter_domain_stmt->def != NULL)
+ {
+ appendStringInfoString(str, "SET DEFAULT ");
+ deparseExpr(str, alter_domain_stmt->def);
+ }
+ else
+ {
+ appendStringInfoString(str, "DROP DEFAULT");
+ }
+ break;
+ case 'N':
+ appendStringInfoString(str, "DROP NOT NULL");
+ break;
+ case 'O':
+ appendStringInfoString(str, "SET NOT NULL");
+ break;
+ case 'C':
+ appendStringInfoString(str, "ADD ");
+ deparseConstraint(str, castNode(Constraint, alter_domain_stmt->def));
+ break;
+ case 'X':
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ if (alter_domain_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ if (alter_domain_stmt->behavior == DROP_CASCADE)
+ appendStringInfoString(str, " CASCADE");
+ break;
+ case 'V':
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ break;
+ default:
+ // No other subtypes supported by the parser
+ Assert(false);
+ }
+}
+
+static void deparseRenameStmt(StringInfo str, RenameStmt *rename_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_COLUMN:
+ switch (rename_stmt->relationType)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ Assert(false);
+ }
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_ATTRIBUTE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (rename_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, rename_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseColId(str, strVal(rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLUMN:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME COLUMN ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(strVal(rename_stmt->object)));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_DOMAIN:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TYPE:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_ATTRIBUTE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
+ appendStringInfoString(str, " RENAME ATTRIBUTE ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->newname));
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDropBehavior(str, rename_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_stmt)
+{
+ ListCell *lc;
+ switch (transaction_stmt->kind)
+ {
+ case TRANS_STMT_BEGIN:
+ appendStringInfoString(str, "BEGIN ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_START:
+ appendStringInfoString(str, "START TRANSACTION ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_COMMIT:
+ appendStringInfoString(str, "COMMIT ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_ROLLBACK:
+ appendStringInfoString(str, "ROLLBACK ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_SAVEPOINT:
+ appendStringInfoString(str, "SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_RELEASE:
+ appendStringInfoString(str, "RELEASE ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_ROLLBACK_TO:
+ appendStringInfoString(str, "ROLLBACK ");
+ appendStringInfoString(str, "TO SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_PREPARE:
+ appendStringInfoString(str, "PREPARE TRANSACTION ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_COMMIT_PREPARED:
+ appendStringInfoString(str, "COMMIT PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_ROLLBACK_PREPARED:
+ appendStringInfoString(str, "ROLLBACK PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
+{
+ ListCell *lc;
+
+ switch (variable_set_stmt->kind)
+ {
+ case VAR_SET_VALUE: /* SET var = value */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO ");
+ deparseVarList(str, variable_set_stmt->args);
+ break;
+ case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO DEFAULT");
+ break;
+ case VAR_SET_CURRENT: /* SET var FROM CURRENT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " FROM CURRENT");
+ break;
+ case VAR_SET_MULTI: /* special case for SET TRANSACTION ... */
+ Assert(variable_set_stmt->name != NULL);
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
+ {
+ appendStringInfoString(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION SNAPSHOT ");
+ deparseStringLiteral(str, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case VAR_RESET: /* RESET var */
+ appendStringInfoString(str, "RESET ");
+ deparseVarName(str, variable_set_stmt->name);
+ break;
+ case VAR_RESET_ALL: /* RESET ALL */
+ appendStringInfoString(str, "RESET ALL");
+ break;
+ }
+}
+
+static void deparseDropdbStmt(StringInfo str, DropdbStmt *dropdb_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "DROP DATABASE ");
+ if (dropdb_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, quote_identifier(dropdb_stmt->dbname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(dropdb_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, dropdb_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "force") == 0)
+ appendStringInfoString(str, "FORCE");
+ else
+ Assert(false); // Currently there are other supported values
+
+ if (lnext(dropdb_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ if (vacuum_stmt->is_vacuumcmd)
+ appendStringInfoString(str, "VACUUM ");
+ else
+ appendStringInfoString(str, "ANALYZE ");
+
+ if (list_length(vacuum_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, vacuum_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(str, def_elem->defname);
+ if (def_elem->arg != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ else
+ Assert(false);
+ }
+ if (lnext(vacuum_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ foreach(lc, vacuum_stmt->rels)
+ {
+ Assert(IsA(lfirst(lc), VacuumRelation));
+ VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
+
+ deparseRangeVar(str, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(rel->va_cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc2, rel->va_cols)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc2))));
+ if (lnext(rel->va_cols, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ if (lnext(vacuum_stmt->rels, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLoadStmt(StringInfo str, LoadStmt *load_stmt)
+{
+ appendStringInfoString(str, "LOAD ");
+ deparseStringLiteral(str, load_stmt->filename);
+}
+
+static void deparseLockStmt(StringInfo str, LockStmt *lock_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "LOCK TABLE ");
+
+ deparseRelationExprList(str, lock_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (lock_stmt->mode != AccessExclusiveLock)
+ {
+ appendStringInfoString(str, "IN ");
+ switch (lock_stmt->mode)
+ {
+ case AccessShareLock:
+ appendStringInfoString(str, "ACCESS SHARE ");
+ break;
+ case RowShareLock:
+ appendStringInfoString(str, "ROW SHARE ");
+ break;
+ case RowExclusiveLock:
+ appendStringInfoString(str, "ROW EXCLUSIVE ");
+ break;
+ case ShareUpdateExclusiveLock:
+ appendStringInfoString(str, "SHARE UPDATE EXCLUSIVE ");
+ break;
+ case ShareLock:
+ appendStringInfoString(str, "SHARE ");
+ break;
+ case ShareRowExclusiveLock:
+ appendStringInfoString(str, "SHARE ROW EXCLUSIVE ");
+ break;
+ case ExclusiveLock:
+ appendStringInfoString(str, "EXCLUSIVE ");
+ break;
+ case AccessExclusiveLock:
+ appendStringInfoString(str, "ACCESS EXCLUSIVE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+ appendStringInfoString(str, "MODE ");
+ }
+
+ if (lock_stmt->nowait)
+ appendStringInfoString(str, "NOWAIT ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraintsSetStmt(StringInfo str, ConstraintsSetStmt *constraints_set_stmt)
+{
+ appendStringInfoString(str, "SET CONSTRAINTS ");
+
+ if (list_length(constraints_set_stmt->constraints) > 0)
+ {
+ deparseQualifiedNameList(str, constraints_set_stmt->constraints);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ if (constraints_set_stmt->deferred)
+ appendStringInfoString(str, "DEFERRED");
+ else
+ appendStringInfoString(str, "IMMEDIATE");
+}
+
+static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ appendStringInfoString(str, "EXPLAIN ");
+
+ if (list_length(explain_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+
+ foreach(lc, explain_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ if (def_elem->arg != NULL && IsA(def_elem->arg, String))
+ {
+ appendStringInfoChar(str, ' ');
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (def_elem->arg != NULL && (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float)))
+ {
+ appendStringInfoChar(str, ' ');
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+
+ if (lnext(explain_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseExplainableStmt(str, explain_stmt->query);
+}
+
+static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "COPY ");
+
+ if (copy_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(copy_stmt->attlist) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, copy_stmt->attlist);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (copy_stmt->query != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, copy_stmt->query);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "FROM ");
+ else
+ appendStringInfoString(str, "TO ");
+
+ if (copy_stmt->is_program)
+ appendStringInfoString(str, "PROGRAM ");
+
+ if (copy_stmt->filename != NULL)
+ {
+ deparseStringLiteral(str, copy_stmt->filename);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "STDIN ");
+ else
+ appendStringInfoString(str, "STDOUT ");
+ }
+
+ if (list_length(copy_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "WITH (");
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "format") == 0)
+ {
+ appendStringInfoString(str, "FORMAT ");
+
+ char *format = strVal(def_elem->arg);
+ if (strcmp(format, "binary") == 0)
+ appendStringInfoString(str, "BINARY");
+ else if (strcmp(format, "csv") == 0)
+ appendStringInfoString(str, "CSV");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "freeze") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
+ {
+ appendStringInfoString(str, "FREEZE");
+ if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
+ appendStringInfoString(str, " 1");
+ }
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
+ {
+ appendStringInfoString(str, "DELIMITER ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "null") == 0)
+ {
+ appendStringInfoString(str, "NULL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "header") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
+ {
+ appendStringInfoString(str, "HEADER");
+ if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
+ appendStringInfoString(str, " 1");
+ }
+ else if (strcmp(def_elem->defname, "quote") == 0)
+ {
+ appendStringInfoString(str, "QUOTE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "escape") == 0)
+ {
+ appendStringInfoString(str, "ESCAPE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
+ {
+ appendStringInfoString(str, "FORCE_QUOTE ");
+ if (IsA(def_elem->arg, A_Star))
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NOT_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "force_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "encoding") == 0)
+ {
+ appendStringInfoString(str, "ENCODING ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL)
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ {
+ // Nothing
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ {
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAStar(str, castNode(A_Star, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoChar(str, '(');
+ foreach(lc2, l)
+ {
+ deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ }
+
+ if (lnext(copy_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseWhereClause(str, copy_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDoStmt(StringInfo str, DoStmt *do_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DO ");
+
+ foreach (lc, do_stmt->args)
+ {
+ DefElem *defel = castNode(DefElem, lfirst(lc));
+ if (strcmp(defel->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(defel->arg)));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defel->defname, "as") == 0)
+ {
+ char *strval = strVal(defel->arg);
+ const char *delim = "$$";
+ if (strstr(strval, "$$") != NULL)
+ delim = "$outer$";
+ appendStringInfoString(str, delim);
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, delim);
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDiscardStmt(StringInfo str, DiscardStmt *discard_stmt)
+{
+ appendStringInfoString(str, "DISCARD ");
+ switch (discard_stmt->target)
+ {
+ case DISCARD_ALL:
+ appendStringInfoString(str, "ALL");
+ break;
+ case DISCARD_PLANS:
+ appendStringInfoString(str, "PLANS");
+ break;
+ case DISCARD_SEQUENCES:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case DISCARD_TEMP:
+ appendStringInfoString(str, "TEMP");
+ break;
+ }
+}
+
+static void deparseDefineStmt(StringInfo str, DefineStmt *define_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (define_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ default:
+ // This shouldn't happen
+ Assert(false);
+ break;
+ }
+
+ if (define_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseFuncName(str, define_stmt->defnames);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAnyOperator(str, define_stmt->defnames);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_COLLATION:
+ deparseAnyName(str, define_stmt->defnames);
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
+ {
+ deparseAggrArgs(str, define_stmt->args);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (define_stmt->kind == OBJECT_COLLATION &&
+ list_length(define_stmt->definition) == 1 &&
+ strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
+ }
+ else if (list_length(define_stmt->definition) > 0)
+ {
+ deparseDefinition(str, define_stmt->definition);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCompositeTypeStmt(StringInfo str, CompositeTypeStmt *composite_type_stmt)
+{
+ ListCell *lc;
+ RangeVar *typevar;
+
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseRangeVar(str, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
+
+ appendStringInfoString(str, " AS (");
+ foreach(lc, composite_type_stmt->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(composite_type_stmt->coldeflist, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateEnumStmt(StringInfo str, CreateEnumStmt *create_enum_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE TYPE ");
+
+ deparseAnyName(str, create_enum_stmt->typeName);
+ appendStringInfoString(str, " AS ENUM (");
+ foreach(lc, create_enum_stmt->vals)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(create_enum_stmt->vals, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateRangeStmt(StringInfo str, CreateRangeStmt *create_range_stmt)
+{
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseAnyName(str, create_range_stmt->typeName);
+ appendStringInfoString(str, " AS RANGE ");
+ deparseDefinition(str, create_range_stmt->params);
+}
+
+static void deparseAlterEnumStmt(StringInfo str, AlterEnumStmt *alter_enum_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_enum_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->oldVal == NULL)
+ {
+ appendStringInfoString(str, "ADD VALUE ");
+ if (alter_enum_stmt->skipIfNewValExists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->newValNeighbor)
+ {
+ if (alter_enum_stmt->newValIsAfter)
+ appendStringInfoString(str, "AFTER ");
+ else
+ appendStringInfoString(str, "BEFORE ");
+ deparseStringLiteral(str, alter_enum_stmt->newValNeighbor);
+ }
+ }
+ else
+ {
+ appendStringInfoString(str, "RENAME VALUE ");
+ deparseStringLiteral(str, alter_enum_stmt->oldVal);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionStmt(StringInfo str, AlterExtensionStmt *alter_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_stmt->extname);
+ appendStringInfoString(str, " UPDATE ");
+ foreach (lc, alter_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionContentsStmt(StringInfo str, AlterExtensionContentsStmt *alter_extension_contents_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_contents_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_extension_contents_stmt->action == 1)
+ appendStringInfoString(str, "ADD ");
+ else if (alter_extension_contents_stmt->action == -1)
+ appendStringInfoString(str, "DROP ");
+ else
+ Assert(false);
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ // No other object types are supported here in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ // any_name
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_TABLE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ deparseAnyName(str, castNode(List, alter_extension_contents_stmt->object));
+ break;
+ // name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_LANGUAGE:
+ case OBJECT_SCHEMA:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ deparseColId(str, strVal(alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ deparseTypeName(str, castNode(TypeName, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
+{
+ ListCell *lc;
+
+ if (access_priv->priv_name != NULL)
+ {
+ if (strcmp(access_priv->priv_name, "select") == 0)
+ appendStringInfoString(str, "select");
+ else if (strcmp(access_priv->priv_name, "references") == 0)
+ appendStringInfoString(str, "references");
+ else if (strcmp(access_priv->priv_name, "create") == 0)
+ appendStringInfoString(str, "create");
+ else
+ appendStringInfoString(str, quote_identifier(access_priv->priv_name));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(access_priv->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, access_priv->cols);
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
+{
+ ListCell *lc;
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "GRANT OPTION FOR ");
+
+ if (list_length(grant_stmt->privileges) > 0)
+ {
+ foreach(lc, grant_stmt->privileges)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_stmt->privileges, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ deparsePrivilegeTarget(str, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ foreach(lc, grant_stmt->grantees)
+ {
+ deparseRoleSpec(str, castNode(RoleSpec, lfirst(lc)));
+ if (lnext(grant_stmt->grantees, lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "WITH GRANT OPTION ");
+
+ deparseOptDropBehavior(str, grant_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
+{
+ ListCell *lc;
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ foreach(lc, grant_role_stmt->granted_roles)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_role_stmt->granted_roles, lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ deparseRoleList(str, grant_role_stmt->grantee_roles);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_role_stmt->admin_opt)
+ appendStringInfoString(str, "WITH ADMIN OPTION ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropRoleStmt(StringInfo str, DropRoleStmt *drop_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DROP ROLE ");
+
+ if (drop_role_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRoleList(str, drop_role_stmt->roles);
+}
+
+static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (index_stmt->unique)
+ appendStringInfoString(str, "UNIQUE ");
+
+ appendStringInfoString(str, "INDEX ");
+
+ if (index_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (index_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (index_stmt->idxname != NULL)
+ {
+ appendStringInfoString(str, index_stmt->idxname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (index_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(index_stmt->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, index_stmt->indexParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+
+ if (list_length(index_stmt->indexIncludingParams) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ foreach (lc, index_stmt->indexIncludingParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexIncludingParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, index_stmt->options);
+
+ if (index_stmt->tableSpace != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(index_stmt->tableSpace));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, index_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterOpFamilyStmt(StringInfo str, AlterOpFamilyStmt *alter_op_family_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR FAMILY ");
+ deparseAnyName(str, alter_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(alter_op_family_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_op_family_stmt->isDrop)
+ appendStringInfoString(str, "DROP ");
+ else
+ appendStringInfoString(str, "ADD ");
+
+ deparseOpclassItemList(str, alter_op_family_stmt->items);
+}
+
+static void deparsePrepareStmt(StringInfo str, PrepareStmt *prepare_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "PREPARE ");
+ deparseColId(str, prepare_stmt->name);
+ if (list_length(prepare_stmt->argtypes) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, prepare_stmt->argtypes);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoString(str, " AS ");
+ deparsePreparableStmt(str, prepare_stmt->query);
+}
+
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "EXECUTE ");
+ appendStringInfoString(str, quote_identifier(execute_stmt->name));
+ if (list_length(execute_stmt->params) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, execute_stmt->params);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseDeallocateStmt(StringInfo str, DeallocateStmt *deallocate_stmt)
+{
+ appendStringInfoString(str, "DEALLOCATE ");
+ if (deallocate_stmt->name != NULL)
+ appendStringInfoString(str, quote_identifier(deallocate_stmt->name));
+ else
+ appendStringInfoString(str, "ALL");
+}
+
+// "AlterOptRoleElem" in gram.y
+static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "password") == 0)
+ {
+ appendStringInfoString(str, "PASSWORD ");
+ if (def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NULL");
+ }
+ else if (IsA(def_elem->arg, ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "connectionlimit") == 0)
+ {
+ appendStringInfo(str, "CONNECTION LIMIT %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validUntil") == 0)
+ {
+ appendStringInfoString(str, "VALID UNTIL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "SUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOSUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOCREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "REPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOREPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOCREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "LOGIN");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOLOGIN");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "BYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOBYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "INHERIT");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOINHERIT");
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "CreateOptRoleElem" in gram.y
+static void deparseCreateRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "sysid") == 0)
+ {
+ appendStringInfo(str, "SYSID %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "adminmembers") == 0)
+ {
+ appendStringInfoString(str, "ADMIN ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "addroleto") == 0)
+ {
+ appendStringInfoString(str, "IN ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ deparseAlterRoleElem(str, def_elem);
+ }
+}
+
+static void deparseCreatePLangStmt(StringInfo str, CreatePLangStmt *create_p_lang_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+
+ if (create_p_lang_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ if (create_p_lang_stmt->pltrusted)
+ appendStringInfoString(str, "TRUSTED ");
+
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, create_p_lang_stmt->plname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_p_lang_stmt->plhandler);
+ appendStringInfoChar(str, ' ');
+
+ if (create_p_lang_stmt->plinline)
+ {
+ appendStringInfoString(str, "INLINE ");
+ deparseHandlerName(str, create_p_lang_stmt->plinline);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_p_lang_stmt->plvalidator)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, create_p_lang_stmt->plvalidator);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateRoleStmt(StringInfo str, CreateRoleStmt *create_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ switch (create_role_stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case ROLESTMT_USER:
+ appendStringInfoString(str, "USER ");
+ break;
+ case ROLESTMT_GROUP:
+ appendStringInfoString(str, "GROUP ");
+ break;
+ }
+
+ appendStringInfoString(str, quote_identifier(create_role_stmt->role));
+ appendStringInfoChar(str, ' ');
+
+ if (create_role_stmt->options != NULL)
+ {
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, create_role_stmt->options)
+ {
+ deparseCreateRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleStmt(StringInfo str, AlterRoleStmt *alter_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "GROUP ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_stmt->action == 1)
+ {
+ appendStringInfoString(str, "ADD USER ");
+ }
+ else if (alter_role_stmt->action == -1)
+ {
+ appendStringInfoString(str, "DROP USER ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseRoleList(str, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, alter_role_stmt->options)
+ {
+ deparseAlterRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeclareCursorStmt(StringInfo str, DeclareCursorStmt *declare_cursor_stmt)
+{
+ appendStringInfoString(str, "DECLARE ");
+ appendStringInfoString(str, quote_identifier(declare_cursor_stmt->portalname));
+ appendStringInfoChar(str, ' ');
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
+ appendStringInfoString(str, "BINARY ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
+ appendStringInfoString(str, "SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
+ appendStringInfoString(str, "NO SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
+ appendStringInfoString(str, "INSENSITIVE ");
+
+ appendStringInfoString(str, "CURSOR ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
+ appendStringInfoString(str, "WITH HOLD ");
+
+ appendStringInfoString(str, "FOR ");
+
+ deparseSelectStmt(str, castNode(SelectStmt, declare_cursor_stmt->query));
+}
+
+static void deparseFetchStmt(StringInfo str, FetchStmt *fetch_stmt)
+{
+ if (fetch_stmt->ismove)
+ appendStringInfoString(str, "MOVE ");
+ else
+ appendStringInfoString(str, "FETCH ");
+
+ switch (fetch_stmt->direction)
+ {
+ case FETCH_FORWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ // Default
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "FORWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_BACKWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "PRIOR ");
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "BACKWARD ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "BACKWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_ABSOLUTE:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "FIRST ");
+ }
+ else if (fetch_stmt->howMany == -1)
+ {
+ appendStringInfoString(str, "LAST ");
+ }
+ else
+ {
+ appendStringInfo(str, "ABSOLUTE %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_RELATIVE:
+ appendStringInfo(str, "RELATIVE %ld ", fetch_stmt->howMany);
+ }
+
+ appendStringInfoString(str, fetch_stmt->portalname);
+}
+
+static void deparseAlterDefaultPrivilegesStmt(StringInfo str, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER DEFAULT PRIVILEGES ");
+
+ foreach (lc, alter_default_privileges_stmt->options)
+ {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp(defelem->defname, "schemas") == 0)
+ {
+ appendStringInfoString(str, "IN SCHEMA ");
+ deparseNameList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defelem->defname, "roles") == 0)
+ {
+ appendStringInfoString(str, "FOR ROLE ");
+ deparseRoleList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ // No other DefElems are supported
+ Assert(false);
+ }
+ }
+
+ deparseGrantStmt(str, alter_default_privileges_stmt->action);
+}
+
+static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
+{
+ appendStringInfoString(str, "REINDEX ");
+
+ if (reindex_stmt->options & REINDEXOPT_VERBOSE)
+ appendStringInfoString(str, "(VERBOSE) ");
+
+ switch (reindex_stmt->kind)
+ {
+ case REINDEX_OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case REINDEX_OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case REINDEX_OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case REINDEX_OBJECT_SYSTEM:
+ appendStringInfoString(str, "SYSTEM ");
+ break;
+ case REINDEX_OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ }
+
+ if (reindex_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (reindex_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (reindex_stmt->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(reindex_stmt->name));
+ }
+}
+
+static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (rule_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "RULE ");
+ appendStringInfoString(str, quote_identifier(rule_stmt->rulename));
+ appendStringInfoString(str, " AS ON ");
+
+ switch (rule_stmt->event)
+ {
+ case CMD_UNKNOWN:
+ case CMD_UTILITY:
+ case CMD_NOTHING:
+ // Not supported here
+ Assert(false);
+ break;
+ case CMD_SELECT:
+ appendStringInfoString(str, "SELECT ");
+ break;
+ case CMD_UPDATE:
+ appendStringInfoString(str, "UPDATE ");
+ break;
+ case CMD_INSERT:
+ appendStringInfoString(str, "INSERT ");
+ break;
+ case CMD_DELETE:
+ appendStringInfoString(str, "DELETE ");
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ deparseRangeVar(str, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseWhereClause(str, rule_stmt->whereClause);
+
+ appendStringInfoString(str, "DO ");
+
+ if (rule_stmt->instead)
+ appendStringInfoString(str, "INSTEAD ");
+
+ if (list_length(rule_stmt->actions) == 0)
+ {
+ appendStringInfoString(str, "NOTHING");
+ }
+ else if (list_length(rule_stmt->actions) == 1)
+ {
+ deparseRuleActionStmt(str, linitial(rule_stmt->actions));
+ }
+ else
+ {
+ appendStringInfoChar(str, '(');
+ foreach (lc, rule_stmt->actions)
+ {
+ deparseRuleActionStmt(str, lfirst(lc));
+ if (lnext(rule_stmt->actions, lc))
+ appendStringInfoString(str, "; ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseNotifyStmt(StringInfo str, NotifyStmt *notify_stmt)
+{
+ appendStringInfoString(str, "NOTIFY ");
+ appendStringInfoString(str, quote_identifier(notify_stmt->conditionname));
+
+ if (notify_stmt->payload != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseStringLiteral(str, notify_stmt->payload);
+ }
+}
+
+static void deparseListenStmt(StringInfo str, ListenStmt *listen_stmt)
+{
+ appendStringInfoString(str, "LISTEN ");
+ appendStringInfoString(str, quote_identifier(listen_stmt->conditionname));
+}
+
+static void deparseUnlistenStmt(StringInfo str, UnlistenStmt *unlisten_stmt)
+{
+ appendStringInfoString(str, "UNLISTEN ");
+ if (unlisten_stmt->conditionname == NULL)
+ appendStringInfoString(str, "*");
+ else
+ appendStringInfoString(str, quote_identifier(unlisten_stmt->conditionname));
+}
+
+static void deparseCreateSeqStmt(StringInfo str, CreateSeqStmt *create_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_seq_stmt->sequence->relpersistence);
+
+ appendStringInfoString(str, "SEQUENCE ");
+
+ if (create_seq_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptSeqOptList(str, create_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFunctionStmt(StringInfo str, AlterFunctionStmt *alter_function_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_function_stmt->objtype)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ deparseFunctionWithArgtypes(str, alter_function_stmt->func);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, alter_function_stmt->actions)
+ {
+ deparseCommonFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ if (lnext(alter_function_stmt->actions, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseTruncateStmt(StringInfo str, TruncateStmt *truncate_stmt)
+{
+ appendStringInfoString(str, "TRUNCATE ");
+
+ deparseRelationExprList(str, truncate_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (truncate_stmt->restart_seqs)
+ appendStringInfoString(str, "RESTART IDENTITY ");
+
+ deparseOptDropBehavior(str, truncate_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateEventTrigStmt(StringInfo str, CreateEventTrigStmt *create_event_trig_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "CREATE EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "ON ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->eventname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_event_trig_stmt->whenclause)
+ {
+ appendStringInfoString(str, "WHEN ");
+
+ foreach (lc, create_event_trig_stmt->whenclause)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " IN (");
+ foreach (lc2, l)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ if (lnext(create_event_trig_stmt->whenclause, lc))
+ appendStringInfoString(str, " AND ");
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_event_trig_stmt->funcname);
+ appendStringInfoString(str, "()");
+}
+
+static void deparseAlterEventTrigStmt(StringInfo str, AlterEventTrigStmt *alter_event_trig_stmt)
+{
+ appendStringInfoString(str, "ALTER EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(alter_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_event_trig_stmt->tgenabled)
+ {
+ case TRIGGER_FIRES_ON_ORIGIN:
+ appendStringInfoString(str, "ENABLE");
+ break;
+ case TRIGGER_FIRES_ON_REPLICA:
+ appendStringInfoString(str, "ENABLE REPLICA");
+ break;
+ case TRIGGER_FIRES_ALWAYS:
+ appendStringInfoString(str, "ENABLE ALWAYS");
+ break;
+ case TRIGGER_DISABLED:
+ appendStringInfoString(str, "DISABLE");
+ break;
+ }
+}
+
+static void deparseRefreshMatViewStmt(StringInfo str, RefreshMatViewStmt *refresh_mat_view_stmt)
+{
+ appendStringInfoString(str, "REFRESH MATERIALIZED VIEW ");
+
+ if (refresh_mat_view_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ deparseRangeVar(str, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (refresh_mat_view_stmt->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt)
+{
+ switch (replica_identity_stmt->identity_type)
+ {
+ case REPLICA_IDENTITY_NOTHING:
+ appendStringInfoString(str, "NOTHING ");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ appendStringInfoString(str, "FULL ");
+ break;
+ case REPLICA_IDENTITY_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ Assert(replica_identity_stmt->name != NULL);
+ appendStringInfoString(str, "USING INDEX ");
+ appendStringInfoString(str, quote_identifier(replica_identity_stmt->name));
+ break;
+ }
+}
+
+static void deparseCreatePolicyStmt(StringInfo str, CreatePolicyStmt *create_policy_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE POLICY ");
+ deparseColId(str, create_policy_stmt->policy_name);
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (!create_policy_stmt->permissive)
+ appendStringInfoString(str, "AS RESTRICTIVE ");
+
+ if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
+ Assert(true); // Default
+ else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
+ appendStringInfoString(str, "FOR SELECT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
+ appendStringInfoString(str, "FOR INSERT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
+ appendStringInfoString(str, "FOR UPDATE ");
+ else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
+ appendStringInfoString(str, "FOR DELETE ");
+ else
+ Assert(false);
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, create_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ if (create_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, create_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (create_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, create_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseAlterPolicyStmt(StringInfo str, AlterPolicyStmt *alter_policy_stmt)
+{
+ appendStringInfoString(str, "ALTER POLICY ");
+ appendStringInfoString(str, quote_identifier(alter_policy_stmt->policy_name));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_policy_stmt->roles) > 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, alter_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, alter_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (alter_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, alter_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *create_table_space_stmt)
+{
+ appendStringInfoString(str, "CREATE TABLESPACE ");
+ deparseColId(str, create_table_space_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_space_stmt->owner != NULL)
+ {
+ appendStringInfoString(str, "OWNER ");
+ deparseRoleSpec(str, create_table_space_stmt->owner);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "LOCATION ");
+ deparseStringLiteral(str, create_table_space_stmt->location);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptWith(str, create_table_space_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTransformStmt(StringInfo str, CreateTransformStmt *create_transform_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_transform_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "TRANSFORM FOR ");
+ deparseTypeName(str, create_transform_stmt->type_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(create_transform_stmt->lang));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoChar(str, '(');
+
+ if (create_transform_stmt->fromsql)
+ {
+ appendStringInfoString(str, "FROM SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->fromsql);
+ }
+
+ if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
+ appendStringInfoString(str, ", ");
+
+ if (create_transform_stmt->tosql)
+ {
+ appendStringInfoString(str, "TO SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->tosql);
+ }
+
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
+{
+ appendStringInfoString(str, "CREATE ACCESS METHOD ");
+ appendStringInfoString(str, quote_identifier(create_am_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TYPE ");
+ switch (create_am_stmt->amtype)
+ {
+ case AMTYPE_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case AMTYPE_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ }
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_am_stmt->handler_name);
+}
+
+static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_publication_stmt->tables) > 0)
+ {
+ appendStringInfoString(str, "FOR TABLE ");
+ deparseRelationExprList(str, create_publication_stmt->tables);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_publication_stmt->for_all_tables)
+ {
+ appendStringInfoString(str, "FOR ALL TABLES ");
+ }
+
+ deparseOptDefinition(str, create_publication_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *alter_publication_stmt)
+{
+ appendStringInfoString(str, "ALTER PUBLICATION ");
+ deparseColId(str, alter_publication_stmt->pubname);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_publication_stmt->tables) > 0)
+ {
+ switch (alter_publication_stmt->tableAction)
+ {
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET TABLE ");
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD TABLE ");
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP TABLE ");
+ break;
+ case DEFELEM_UNSPEC:
+ Assert(false);
+ break;
+ }
+
+ deparseRelationExprList(str, alter_publication_stmt->tables);
+ }
+ else if (list_length(alter_publication_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_publication_stmt->options);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+static void deparseAlterSeqStmt(StringInfo str, AlterSeqStmt *alter_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SEQUENCE ");
+
+ if (alter_seq_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseSeqOptList(str, alter_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSystemStmt(StringInfo str, AlterSystemStmt *alter_system_stmt)
+{
+ appendStringInfoString(str, "ALTER SYSTEM ");
+ deparseVariableSetStmt(str, alter_system_stmt->setstmt);
+}
+
+static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "COMMENT ON ");
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ deparseAnyName(str, castNode(List, comment_stmt->object));
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(strVal(comment_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ deparseTypeName(str, castNode(TypeName, comment_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON DOMAIN ");
+ deparseTypeName(str, linitial(l));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(lsecond(l))));
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, comment_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseValue(str, (Value *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (comment_stmt->comment != NULL)
+ deparseStringLiteral(str, comment_stmt->comment);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE STATISTICS ");
+
+ if (create_stats_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseAnyName(str, create_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_stats_stmt->stat_types) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, create_stats_stmt->stat_types);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseExprList(str, create_stats_stmt->exprs);
+
+ appendStringInfoString(str, " FROM ");
+ deparseFromList(str, create_stats_stmt->relations);
+}
+
+static void deparseAlterCollationStmt(StringInfo str, AlterCollationStmt *alter_collation_stmt)
+{
+ appendStringInfoString(str, "ALTER COLLATION ");
+ deparseAnyName(str, alter_collation_stmt->collname);
+ appendStringInfoString(str, " REFRESH VERSION");
+}
+
+static void deparseAlterDatabaseStmt(StringInfo str, AlterDatabaseStmt *alter_database_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, alter_database_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterDatabaseSetStmt(StringInfo str, AlterDatabaseSetStmt *alter_database_set_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_set_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseVariableSetStmt(str, alter_database_set_stmt->setstmt);
+}
+
+static void deparseAlterStatsStmt(StringInfo str, AlterStatsStmt *alter_stats_stmt)
+{
+ appendStringInfoString(str, "ALTER STATISTICS ");
+
+ if (alter_stats_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseAnyName(str, alter_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfo(str, "SET STATISTICS %d", alter_stats_stmt->stxstattarget);
+}
+
+static void deparseAlterTSDictionaryStmt(StringInfo str, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
+{
+ appendStringInfoString(str, "ALTER TEXT SEARCH DICTIONARY ");
+
+ deparseAnyName(str, alter_ts_dictionary_stmt->dictname);
+ appendStringInfoChar(str, ' ');
+
+ deparseDefinition(str, alter_ts_dictionary_stmt->options);
+}
+
+static void deparseAlterTSConfigurationStmt(StringInfo str, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, alter_ts_configuration_stmt->cfgname);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_ts_configuration_stmt->kind)
+ {
+ case ALTER_TSCONFIG_ADD_MAPPING:
+ appendStringInfoString(str, "ADD MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT:
+ appendStringInfoString(str, "ALTER MAPPING REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_DROP_MAPPING:
+ appendStringInfoString(str, "DROP MAPPING ");
+ if (alter_ts_configuration_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, "FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ break;
+ }
+}
+
+static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_show_stmt)
+{
+ appendStringInfoString(str, "SHOW ");
+
+ if (strcmp(variable_show_stmt->name, "timezone") == 0)
+ appendStringInfoString(str, "TIME ZONE");
+ else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
+ appendStringInfoString(str, "TRANSACTION ISOLATION LEVEL");
+ else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
+ appendStringInfoString(str, "SESSION AUTHORIZATION");
+ else if (strcmp(variable_show_stmt->name, "all") == 0)
+ appendStringInfoString(str, "SESSION ALL");
+ else
+ appendStringInfoString(str, variable_show_stmt->name);
+}
+
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
+{
+ deparseRangeVar(str, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
+
+ appendStringInfoString(str, " TABLESAMPLE ");
+
+ deparseFuncName(str, range_table_sample->method);
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, range_table_sample->args);
+ appendStringInfoString(str, ") ");
+
+ if (range_table_sample->repeatable != NULL)
+ {
+ appendStringInfoString(str, "REPEATABLE (");
+ deparseExpr(str, range_table_sample->repeatable);
+ appendStringInfoString(str, ") ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateSubscriptionStmt(StringInfo str, CreateSubscriptionStmt *create_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(create_subscription_stmt->subname));
+
+ appendStringInfoString(str, " CONNECTION ");
+ if (create_subscription_stmt->conninfo != NULL)
+ deparseStringLiteral(str, create_subscription_stmt->conninfo);
+ else
+ appendStringInfoString(str, "''");
+
+ appendStringInfoString(str, " PUBLICATION ");
+
+ foreach(lc, create_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(create_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDefinition(str, create_subscription_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *alter_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(alter_subscription_stmt->subname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_subscription_stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ appendStringInfoString(str, "CONNECTION ");
+ deparseStringLiteral(str, alter_subscription_stmt->conninfo);
+ appendStringInfoChar(str, ' ');
+ break;
+ case ALTER_SUBSCRIPTION_REFRESH:
+ appendStringInfoString(str, "REFRESH PUBLICATION ");
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_PUBLICATION:
+ appendStringInfoString(str, "SET PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ENABLED:
+ Assert(list_length(alter_subscription_stmt->options) == 1);
+ DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
+ Assert(strcmp(defelem->defname, "enabled") == 0);
+ if (intVal(defelem->arg) == 1)
+ {
+ appendStringInfoString(str, " ENABLE ");
+ }
+ else if (intVal(defelem->arg) == 0)
+ {
+ appendStringInfoString(str, " DISABLE ");
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropSubscriptionStmt(StringInfo str, DropSubscriptionStmt *drop_subscription_stmt)
+{
+ appendStringInfoString(str, "DROP SUBSCRIPTION ");
+
+ if (drop_subscription_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_subscription_stmt->subname);
+}
+
+static void deparseCallStmt(StringInfo str, CallStmt *call_stmt)
+{
+ appendStringInfoString(str, "CALL ");
+ deparseFuncCall(str, call_stmt->funccall);
+}
+
+static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_owner_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnly(str, (Value *) alter_owner_stmt->object);
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ default:
+ Assert(false);
+ }
+
+ appendStringInfoString(str, " OWNER TO ");
+ deparseRoleSpec(str, alter_owner_stmt->newowner);
+}
+
+// "operator_def_list" in gram.y
+static void deparseOperatorDefList(StringInfo str, List *defs)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, defs)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " = ");
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, true);
+ else
+ appendStringInfoString(str, "NONE");
+
+ if (lnext(defs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterOperatorStmt(StringInfo str, AlterOperatorStmt *alter_operator_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR ");
+ deparseOperatorWithArgtypes(str, alter_operator_stmt->opername);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_operator_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseAlterTypeStmt(StringInfo str, AlterTypeStmt *alter_type_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_type_stmt->typeName);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_type_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseDropOwnedStmt(StringInfo str, DropOwnedStmt *drop_owned_stmt)
+{
+ appendStringInfoString(str, "DROP OWNED BY ");
+ deparseRoleList(str, drop_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ deparseOptDropBehavior(str, drop_owned_stmt->behavior);
+ removeTrailingSpace(str);
+}
+
+static void deparseReassignOwnedStmt(StringInfo str, ReassignOwnedStmt *reassigned_owned_stmt)
+{
+ appendStringInfoString(str, "REASSIGN OWNED BY ");
+
+ deparseRoleList(str, reassigned_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleSpec(str, reassigned_owned_stmt->newrole);
+}
+
+static void deparseClosePortalStmt(StringInfo str, ClosePortalStmt *close_portal_stmt)
+{
+ appendStringInfoString(str, "CLOSE ");
+ if (close_portal_stmt->portalname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(close_portal_stmt->portalname));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+}
+
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr)
+{
+ appendStringInfoString(str, "CURRENT OF ");
+ appendStringInfoString(str, quote_identifier(current_of_expr->cursor_name));
+}
+
+static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_stmt)
+{
+ ListCell *lc;
+ bool skip_events_or = true;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_trig_stmt->isconstraint)
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, "TRIGGER ");
+
+ appendStringInfoString(str, quote_identifier(create_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (create_trig_stmt->timing)
+ {
+ case TRIGGER_TYPE_BEFORE:
+ appendStringInfoString(str, "BEFORE ");
+ break;
+ case TRIGGER_TYPE_AFTER:
+ appendStringInfoString(str, "AFTER ");
+ break;
+ case TRIGGER_TYPE_INSTEAD:
+ appendStringInfoString(str, "INSTEAD OF ");
+ break;
+ default:
+ Assert(false);
+ }
+
+ if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
+ {
+ appendStringInfoString(str, "INSERT ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "DELETE ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "UPDATE ");
+ if (list_length(create_trig_stmt->columns) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseColumnList(str, create_trig_stmt->columns);
+ appendStringInfoChar(str, ' ');
+ }
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "TRUNCATE ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_trig_stmt->transitionRels != NULL)
+ {
+ appendStringInfoString(str, "REFERENCING ");
+ foreach(lc, create_trig_stmt->transitionRels)
+ {
+ deparseTriggerTransition(str, castNode(TriggerTransition, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ if (create_trig_stmt->constrrel != NULL)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseRangeVar(str, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_trig_stmt->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (create_trig_stmt->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (create_trig_stmt->row)
+ appendStringInfoString(str, "FOR EACH ROW ");
+
+ if (create_trig_stmt->whenClause)
+ {
+ appendStringInfoString(str, "WHEN (");
+ deparseExpr(str, create_trig_stmt->whenClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_trig_stmt->funcname);
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_trig_stmt->args)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(create_trig_stmt->args, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition)
+{
+ if (trigger_transition->isNew)
+ appendStringInfoString(str, "NEW ");
+ else
+ appendStringInfoString(str, "OLD ");
+
+ if (trigger_transition->isTable)
+ appendStringInfoString(str, "TABLE ");
+ else
+ appendStringInfoString(str, "ROW ");
+
+ appendStringInfoString(str, quote_identifier(trigger_transition->name));
+}
+
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
+{
+ switch (xml_expr->op)
+ {
+ case IS_XMLCONCAT: /* XMLCONCAT(args) */
+ appendStringInfoString(str, "xmlconcat(");
+ deparseExprList(str, xml_expr->args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
+ appendStringInfoString(str, "xmlelement(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->named_args != NULL)
+ {
+ appendStringInfoString(str, ", xmlattributes(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoString(str, ")");
+ }
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExprList(str, xml_expr->args);
+ }
+ appendStringInfoString(str, ")");
+ break;
+ case IS_XMLFOREST: /* XMLFOREST(xml_attributes) */
+ appendStringInfoString(str, "xmlforest(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
+ Assert(list_length(xml_expr->args) == 2);
+ appendStringInfoString(str, "xmlparse(");
+ switch (xml_expr->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, linitial(xml_expr->args));
+ if (strcmp(strVal(&castNode(A_Const, castNode(TypeCast, lsecond(xml_expr->args))->arg)->val), "t") == 0)
+ appendStringInfoString(str, " PRESERVE WHITESPACE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPI: /* XMLPI(name [, args]) */
+ appendStringInfoString(str, "xmlpi(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, linitial(xml_expr->args));
+ }
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
+ appendStringInfoString(str, "xmlroot(");
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, ", version ");
+ if (nodeTag(&castNode(A_Const, lsecond(xml_expr->args))->val) == T_Null)
+ appendStringInfoString(str, "NO VALUE");
+ else
+ deparseExpr(str, lsecond(xml_expr->args));
+ if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
+ appendStringInfoString(str, ", STANDALONE YES");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
+ appendStringInfoString(str, ", STANDALONE NO");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
+ appendStringInfoString(str, ", STANDALONE NO VALUE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLSERIALIZE: /* XMLSERIALIZE(is_document, xmlval) */
+ // These are represented as XmlSerialize in raw parse trees
+ Assert(false);
+ break;
+ case IS_DOCUMENT: /* xmlval IS DOCUMENT */
+ Assert(list_length(xml_expr->args) == 1);
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, " IS DOCUMENT");
+ break;
+ }
+}
+
+static void deparseRangeTableFuncCol(StringInfo str, RangeTableFuncCol* range_table_func_col)
+{
+ appendStringInfoString(str, quote_identifier(range_table_func_col->colname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->for_ordinality)
+ {
+ appendStringInfoString(str, "FOR ORDINALITY ");
+ }
+ else
+ {
+ deparseTypeName(str, range_table_func_col->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->colexpr)
+ {
+ appendStringInfoString(str, "PATH ");
+ deparseExpr(str, range_table_func_col->colexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->coldefexpr)
+ {
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, range_table_func_col->coldefexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->is_not_null)
+ appendStringInfoString(str, "NOT NULL ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func)
+{
+ ListCell *lc;
+
+ if (range_table_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoString(str, "xmltable(");
+ if (range_table_func->namespaces)
+ {
+ appendStringInfoString(str, "xmlnamespaces(");
+ deparseXmlNamespaceList(str, range_table_func->namespaces);
+ appendStringInfoString(str, "), ");
+ }
+
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, range_table_func->rowexpr);
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, range_table_func->docexpr);
+
+ appendStringInfoString(str, " COLUMNS ");
+ foreach(lc, range_table_func->columns)
+ {
+ deparseRangeTableFuncCol(str, castNode(RangeTableFuncCol, lfirst(lc)));
+ if (lnext(range_table_func->columns, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, ") ");
+
+ if (range_table_func->alias)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_table_func->alias);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize)
+{
+ appendStringInfoString(str, "xmlserialize(");
+ switch (xml_serialize->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, xml_serialize->expr);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, xml_serialize->typeName);
+ appendStringInfoString(str, ")");
+}
+
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
+{
+ appendStringInfoString(str, "GROUPING(");
+ deparseExprList(str, grouping_func->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
+{
+ appendStringInfoString(str, "CLUSTER ");
+ if (cluster_stmt->options & CLUOPT_VERBOSE)
+ appendStringInfoString(str, "VERBOSE ");
+
+ if (cluster_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (cluster_stmt->indexname != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(cluster_stmt->indexname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ case T_Float:
+ deparseNumericOnly(str, value);
+ break;
+ case T_String:
+ if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
+ appendStringInfoString(str, quote_identifier(value->val.str));
+ } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
+ deparseStringLiteral(str, value->val.str);
+ } else {
+ appendStringInfoString(str, value->val.str);
+ }
+ break;
+ case T_BitString:
+ if (strlen(value->val.str) >= 1 && value->val.str[0] == 'x')
+ {
+ appendStringInfoChar(str, 'x');
+ deparseStringLiteral(str, value->val.str + 1);
+ }
+ else if (strlen(value->val.str) >= 1 && value->val.str[0] == 'b')
+ {
+ appendStringInfoChar(str, 'b');
+ deparseStringLiteral(str, value->val.str + 1);
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case T_Null:
+ appendStringInfoString(str, "NULL");
+ break;
+ default:
+ elog(ERROR, "deparse: unrecognized value node type: %d",
+ (int) nodeTag(value));
+ break;
+ }
+}
+
+// "PrepareableStmt" in gram.y
+static void deparsePreparableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "RuleActionStmt" in gram.y
+static void deparseRuleActionStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "ExplainableStmt" in gram.y
+static void deparseExplainableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_CreateTableAsStmt:
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "schema_stmt" in gram.y
+static void deparseSchemaStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "stmt" in gram.y
+static void deparseStmt(StringInfo str, Node *node)
+{
+ // Note the following grammar names are missing in the list, because they
+ // get mapped to other node types:
+ //
+ // - AlterForeignTableStmt (=> AlterTableStmt)
+ // - AlterGroupStmt (=> AlterRoleStmt)
+ // - AlterCompositeTypeStmt (=> AlterTableStmt)
+ // - AnalyzeStmt (=> VacuumStmt)
+ // - CreateGroupStmt (=> CreateRoleStmt)
+ // - CreateMatViewStmt (=> CreateTableAsStmt)
+ // - CreateUserStmt (=> CreateRoleStmt)
+ // - DropCastStmt (=> DropStmt)
+ // - DropOpClassStmt (=> DropStmt)
+ // - DropOpFamilyStmt (=> DropStmt)
+ // - DropPLangStmt (=> DropPLangStmt)
+ // - DropTransformStmt (=> DropStmt)
+ // - RemoveAggrStmt (=> DropStmt)
+ // - RemoveFuncStmt (=> DropStmt)
+ // - RemoveOperStmt (=> DropStmt)
+ // - RevokeStmt (=> GrantStmt)
+ // - RevokeRoleStmt (=> GrantRoleStmt)
+ // - VariableResetStmt (=> VariableSetStmt)
+ //
+ // And the following grammar names error out in the parser:
+ // - CreateAssertionStmt (not supported yet)
+ switch (nodeTag(node))
+ {
+ case T_AlterEventTrigStmt:
+ deparseAlterEventTrigStmt(str, castNode(AlterEventTrigStmt, node));
+ break;
+ case T_AlterCollationStmt:
+ deparseAlterCollationStmt(str, castNode(AlterCollationStmt, node));
+ break;
+ case T_AlterDatabaseStmt:
+ deparseAlterDatabaseStmt(str, castNode(AlterDatabaseStmt, node));
+ break;
+ case T_AlterDatabaseSetStmt:
+ deparseAlterDatabaseSetStmt(str, castNode(AlterDatabaseSetStmt, node));
+ break;
+ case T_AlterDefaultPrivilegesStmt:
+ deparseAlterDefaultPrivilegesStmt(str, castNode(AlterDefaultPrivilegesStmt, node));
+ break;
+ case T_AlterDomainStmt:
+ deparseAlterDomainStmt(str, castNode(AlterDomainStmt, node));
+ break;
+ case T_AlterEnumStmt:
+ deparseAlterEnumStmt(str, castNode(AlterEnumStmt, node));
+ break;
+ case T_AlterExtensionStmt:
+ deparseAlterExtensionStmt(str, castNode(AlterExtensionStmt, node));
+ break;
+ case T_AlterExtensionContentsStmt:
+ deparseAlterExtensionContentsStmt(str, castNode(AlterExtensionContentsStmt, node));
+ break;
+ case T_AlterFdwStmt:
+ deparseAlterFdwStmt(str, castNode(AlterFdwStmt, node));
+ break;
+ case T_AlterForeignServerStmt:
+ deparseAlterForeignServerStmt(str, castNode(AlterForeignServerStmt, node));
+ break;
+ case T_AlterFunctionStmt:
+ deparseAlterFunctionStmt(str, castNode(AlterFunctionStmt, node));
+ break;
+ case T_AlterObjectDependsStmt:
+ deparseAlterObjectDependsStmt(str, castNode(AlterObjectDependsStmt, node));
+ break;
+ case T_AlterObjectSchemaStmt:
+ deparseAlterObjectSchemaStmt(str, castNode(AlterObjectSchemaStmt, node));
+ break;
+ case T_AlterOwnerStmt:
+ deparseAlterOwnerStmt(str, castNode(AlterOwnerStmt, node));
+ break;
+ case T_AlterOperatorStmt:
+ deparseAlterOperatorStmt(str, castNode(AlterOperatorStmt, node));
+ break;
+ case T_AlterTypeStmt:
+ deparseAlterTypeStmt(str, castNode(AlterTypeStmt, node));
+ break;
+ case T_AlterPolicyStmt:
+ deparseAlterPolicyStmt(str, castNode(AlterPolicyStmt, node));
+ break;
+ case T_AlterSeqStmt:
+ deparseAlterSeqStmt(str, castNode(AlterSeqStmt, node));
+ break;
+ case T_AlterSystemStmt:
+ deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
+ break;
+ case T_AlterTableStmt:
+ deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
+ break;
+ case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
+ deparseAlterTableSpaceOptionsStmt(str, castNode(AlterTableSpaceOptionsStmt, node));
+ break;
+ case T_AlterPublicationStmt:
+ deparseAlterPublicationStmt(str, castNode(AlterPublicationStmt, node));
+ break;
+ case T_AlterRoleSetStmt:
+ deparseAlterRoleSetStmt(str, castNode(AlterRoleSetStmt, node));
+ break;
+ case T_AlterRoleStmt:
+ deparseAlterRoleStmt(str, castNode(AlterRoleStmt, node));
+ break;
+ case T_AlterSubscriptionStmt:
+ deparseAlterSubscriptionStmt(str, castNode(AlterSubscriptionStmt, node));
+ break;
+ case T_AlterStatsStmt:
+ deparseAlterStatsStmt(str, castNode(AlterStatsStmt, node));
+ break;
+ case T_AlterTSConfigurationStmt:
+ deparseAlterTSConfigurationStmt(str, castNode(AlterTSConfigurationStmt, node));
+ break;
+ case T_AlterTSDictionaryStmt:
+ deparseAlterTSDictionaryStmt(str, castNode(AlterTSDictionaryStmt, node));
+ break;
+ case T_AlterUserMappingStmt:
+ deparseAlterUserMappingStmt(str, castNode(AlterUserMappingStmt, node));
+ break;
+ case T_CallStmt:
+ deparseCallStmt(str, castNode(CallStmt, node));
+ break;
+ case T_CheckPointStmt:
+ deparseCheckPointStmt(str, castNode(CheckPointStmt, node));
+ break;
+ case T_ClosePortalStmt:
+ deparseClosePortalStmt(str, castNode(ClosePortalStmt, node));
+ break;
+ case T_ClusterStmt:
+ deparseClusterStmt(str, castNode(ClusterStmt, node));
+ break;
+ case T_CommentStmt:
+ deparseCommentStmt(str, castNode(CommentStmt, node));
+ break;
+ case T_ConstraintsSetStmt:
+ deparseConstraintsSetStmt(str, castNode(ConstraintsSetStmt, node));
+ break;
+ case T_CopyStmt:
+ deparseCopyStmt(str, castNode(CopyStmt, node));
+ break;
+ case T_CreateAmStmt:
+ deparseCreateAmStmt(str, castNode(CreateAmStmt, node));
+ break;
+ case T_CreateTableAsStmt: // "CreateAsStmt" in gram.y
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_CreateCastStmt:
+ deparseCreateCastStmt(str, castNode(CreateCastStmt, node));
+ break;
+ case T_CreateConversionStmt:
+ deparseCreateConversionStmt(str, castNode(CreateConversionStmt, node));
+ break;
+ case T_CreateDomainStmt:
+ deparseCreateDomainStmt(str, castNode(CreateDomainStmt, node));
+ break;
+ case T_CreateExtensionStmt:
+ deparseCreateExtensionStmt(str, castNode(CreateExtensionStmt, node));
+ break;
+ case T_CreateFdwStmt:
+ deparseCreateFdwStmt(str, castNode(CreateFdwStmt, node));
+ break;
+ case T_CreateForeignServerStmt:
+ deparseCreateForeignServerStmt(str, castNode(CreateForeignServerStmt, node));
+ break;
+ case T_CreateForeignTableStmt:
+ deparseCreateForeignTableStmt(str, castNode(CreateForeignTableStmt, node));
+ break;
+ case T_CreateFunctionStmt:
+ deparseCreateFunctionStmt(str, castNode(CreateFunctionStmt, node));
+ break;
+ case T_CreateOpClassStmt:
+ deparseCreateOpClassStmt(str, castNode(CreateOpClassStmt, node));
+ break;
+ case T_CreateOpFamilyStmt:
+ deparseCreateOpFamilyStmt(str, castNode(CreateOpFamilyStmt, node));
+ break;
+ case T_CreatePublicationStmt:
+ deparseCreatePublicationStmt(str, castNode(CreatePublicationStmt, node));
+ break;
+ case T_AlterOpFamilyStmt:
+ deparseAlterOpFamilyStmt(str, castNode(AlterOpFamilyStmt, node));
+ break;
+ case T_CreatePolicyStmt:
+ deparseCreatePolicyStmt(str, castNode(CreatePolicyStmt, node));
+ break;
+ case T_CreatePLangStmt:
+ deparseCreatePLangStmt(str, castNode(CreatePLangStmt, node));
+ break;
+ case T_CreateSchemaStmt:
+ deparseCreateSchemaStmt(str, castNode(CreateSchemaStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_CreateSubscriptionStmt:
+ deparseCreateSubscriptionStmt(str, castNode(CreateSubscriptionStmt, node));
+ break;
+ case T_CreateStatsStmt:
+ deparseCreateStatsStmt(str, castNode(CreateStatsStmt, node));
+ break;
+ case T_CreateTableSpaceStmt:
+ deparseCreateTableSpaceStmt(str, castNode(CreateTableSpaceStmt, node));
+ break;
+ case T_CreateTransformStmt:
+ deparseCreateTransformStmt(str, castNode(CreateTransformStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_CreateEventTrigStmt:
+ deparseCreateEventTrigStmt(str, castNode(CreateEventTrigStmt, node));
+ break;
+ case T_CreateRoleStmt:
+ deparseCreateRoleStmt(str, castNode(CreateRoleStmt, node));
+ break;
+ case T_CreateUserMappingStmt:
+ deparseCreateUserMappingStmt(str, castNode(CreateUserMappingStmt, node));
+ break;
+ case T_CreatedbStmt:
+ deparseCreatedbStmt(str, castNode(CreatedbStmt, node));
+ break;
+ case T_DeallocateStmt:
+ deparseDeallocateStmt(str, castNode(DeallocateStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_DefineStmt:
+ deparseDefineStmt(str, castNode(DefineStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DiscardStmt:
+ deparseDiscardStmt(str, castNode(DiscardStmt, node));
+ break;
+ case T_DoStmt:
+ deparseDoStmt(str, castNode(DoStmt, node));
+ break;
+ case T_DropOwnedStmt:
+ deparseDropOwnedStmt(str, castNode(DropOwnedStmt, node));
+ break;
+ case T_DropStmt:
+ deparseDropStmt(str, castNode(DropStmt, node));
+ break;
+ case T_DropSubscriptionStmt:
+ deparseDropSubscriptionStmt(str, castNode(DropSubscriptionStmt, node));
+ break;
+ case T_DropTableSpaceStmt:
+ deparseDropTableSpaceStmt(str, castNode(DropTableSpaceStmt, node));
+ break;
+ case T_DropRoleStmt:
+ deparseDropRoleStmt(str, castNode(DropRoleStmt, node));
+ break;
+ case T_DropUserMappingStmt:
+ deparseDropUserMappingStmt(str, castNode(DropUserMappingStmt, node));
+ break;
+ case T_DropdbStmt:
+ deparseDropdbStmt(str, castNode(DropdbStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ case T_ExplainStmt:
+ deparseExplainStmt(str, castNode(ExplainStmt, node));
+ break;
+ case T_FetchStmt:
+ deparseFetchStmt(str, castNode(FetchStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_GrantRoleStmt:
+ deparseGrantRoleStmt(str, castNode(GrantRoleStmt, node));
+ break;
+ case T_ImportForeignSchemaStmt:
+ deparseImportForeignSchemaStmt(str, castNode(ImportForeignSchemaStmt, node));
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_ListenStmt:
+ deparseListenStmt(str, castNode(ListenStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_LoadStmt:
+ deparseLoadStmt(str, castNode(LoadStmt, node));
+ break;
+ case T_LockStmt:
+ deparseLockStmt(str, castNode(LockStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ case T_PrepareStmt:
+ deparsePrepareStmt(str, castNode(PrepareStmt, node));
+ break;
+ case T_ReassignOwnedStmt:
+ deparseReassignOwnedStmt(str, castNode(ReassignOwnedStmt, node));
+ break;
+ case T_ReindexStmt:
+ deparseReindexStmt(str, castNode(ReindexStmt, node));
+ break;
+ case T_RenameStmt:
+ deparseRenameStmt(str, castNode(RenameStmt, node));
+ break;
+ case T_RuleStmt:
+ deparseRuleStmt(str, castNode(RuleStmt, node));
+ break;
+ case T_SecLabelStmt:
+ deparseSecLabelStmt(str, castNode(SecLabelStmt, node));
+ break;
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_TransactionStmt:
+ deparseTransactionStmt(str, castNode(TransactionStmt, node));
+ break;
+ case T_TruncateStmt:
+ deparseTruncateStmt(str, castNode(TruncateStmt, node));
+ break;
+ case T_UnlistenStmt:
+ deparseUnlistenStmt(str, castNode(UnlistenStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_VacuumStmt:
+ deparseVacuumStmt(str, castNode(VacuumStmt, node));
+ break;
+ case T_VariableSetStmt:
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, node));
+ break;
+ case T_VariableShowStmt:
+ deparseVariableShowStmt(str, castNode(VariableShowStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ // These node types are created by DefineStmt grammar for CREATE TYPE in some cases
+ case T_CompositeTypeStmt:
+ deparseCompositeTypeStmt(str, castNode(CompositeTypeStmt, node));
+ break;
+ case T_CreateEnumStmt:
+ deparseCreateEnumStmt(str, castNode(CreateEnumStmt, node));
+ break;
+ case T_CreateRangeStmt:
+ deparseCreateRangeStmt(str, castNode(CreateRangeStmt, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
+ }
+}
+#endif
diff --git a/postgres_deparse.14.c b/postgres_deparse.14.c
new file mode 100644
index 0000000..dc1bbe2
--- /dev/null
+++ b/postgres_deparse.14.c
@@ -0,0 +1,10295 @@
+#include "pg_config.h"
+#if(PG_MAJORVERSION_NUM == 14)
+
+// Adapted from https://github.com/pganalyze/libpg_query/blob/14-3.0.0/src/pg_query_deparse.c
+
+// Copyright (c) 2015, Lukas Fittl
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "postgres.h"
+#include "catalog/index.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_trigger.h"
+#include "commands/trigger.h"
+#include "common/keywords.h"
+#include "common/kwlookup.h"
+#include "lib/stringinfo.h"
+#include "limits.h"
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "utils/builtins.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/xml.h"
+
+typedef enum DeparseNodeContext {
+ DEPARSE_NODE_CONTEXT_NONE,
+ // Parent node type (and sometimes field)
+ DEPARSE_NODE_CONTEXT_INSERT_RELATION,
+ DEPARSE_NODE_CONTEXT_INSERT_ON_CONFLICT,
+ DEPARSE_NODE_CONTEXT_UPDATE,
+ DEPARSE_NODE_CONTEXT_RETURNING,
+ DEPARSE_NODE_CONTEXT_A_EXPR,
+ DEPARSE_NODE_CONTEXT_XMLATTRIBUTES,
+ DEPARSE_NODE_CONTEXT_XMLNAMESPACES,
+ DEPARSE_NODE_CONTEXT_CREATE_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_TYPE,
+ // Identifier vs constant context
+ DEPARSE_NODE_CONTEXT_IDENTIFIER,
+ DEPARSE_NODE_CONTEXT_CONSTANT
+} DeparseNodeContext;
+
+static void
+removeTrailingSpace(StringInfo str)
+{
+ if (str->len >= 1 && str->data[str->len - 1] == ' ') {
+ str->len -= 1;
+ str->data[str->len] = '\0';
+ }
+}
+
+/*
+ * Append a SQL string literal representing "val" to buf.
+ *
+ * Copied here from postgres_fdw/deparse.c to avoid adding
+ * many additional dependencies.
+ */
+static void
+deparseStringLiteral(StringInfo buf, const char *val)
+{
+ const char *valptr;
+
+ /*
+ * Rather than making assumptions about the remote server's value of
+ * standard_conforming_strings, always use E'foo' syntax if there are any
+ * backslashes. This will fail on remote servers before 8.1, but those
+ * are long out of support.
+ */
+ if (strchr(val, '\\') != NULL)
+ appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
+ appendStringInfoChar(buf, '\'');
+ for (valptr = val; *valptr; valptr++)
+ {
+ char ch = *valptr;
+
+ if (SQL_STR_DOUBLE(ch, true))
+ appendStringInfoChar(buf, ch);
+ appendStringInfoChar(buf, ch);
+ }
+ appendStringInfoChar(buf, '\'');
+}
+
+// Check whether the value is a reserved keyword, to determine escaping for output
+//
+// Note that since the parser lowercases all keywords, this does *not* match when the
+// value is not all-lowercase and a reserved keyword.
+static bool
+isReservedKeyword(const char *val)
+{
+ int kwnum = ScanKeywordLookup(val, &ScanKeywords);
+ bool all_lower_case = true;
+ const char *cp;
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ (*cp >= 'a' && *cp <= 'z') ||
+ (*cp >= '0' && *cp <= '9') ||
+ (*cp == '_')))
+ {
+ all_lower_case = false;
+ break;
+ }
+ }
+
+ return all_lower_case && kwnum >= 0 && ScanKeywordCategories[kwnum] == RESERVED_KEYWORD;
+}
+
+// Returns whether the given value consists only of operator characters
+static bool
+isOp(const char *val)
+{
+ const char *cp;
+
+ Assert(strlen(val) > 0);
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ *cp == '~' ||
+ *cp == '!' ||
+ *cp == '@' ||
+ *cp == '#' ||
+ *cp == '^' ||
+ *cp == '&' ||
+ *cp == '|' ||
+ *cp == '`' ||
+ *cp == '?' ||
+ *cp == '+' ||
+ *cp == '-' ||
+ *cp == '*' ||
+ *cp == '/' ||
+ *cp == '%' ||
+ *cp == '<' ||
+ *cp == '>' ||
+ *cp == '='))
+ return false;
+ }
+
+ return true;
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt);
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause);
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context);
+static void deparseResTarget(StringInfo str, ResTarget *res_target, DeparseNodeContext context);
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt);
+static void deparseAlias(StringInfo str, Alias *alias);
+static void deparseWindowDef(StringInfo str, WindowDef* window_def);
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref);
+static void deparseSubLink(StringInfo str, SubLink* sub_link);
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context);
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr);
+static void deparseAStar(StringInfo str, A_Star* a_star);
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause);
+static void deparseSortBy(StringInfo str, SortBy* sort_by);
+static void deparseParamRef(StringInfo str, ParamRef* param_ref);
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function);
+static void deparseWithClause(StringInfo str, WithClause *with_clause);
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr);
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte);
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect);
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func);
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr * array_expr);
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr);
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast);
+static void deparseTypeName(StringInfo str, TypeName *type_name);
+static void deparseNullTest(StringInfo str, NullTest *null_test);
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr);
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when);
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection);
+static void deparseAIndices(StringInfo str, A_Indices *a_indices);
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr);
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test);
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def);
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt);
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause);
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem);
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt);
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt);
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause);
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default);
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt);
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt);
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter);
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec);
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt);
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt);
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt);
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample);
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func);
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set);
+static void deparseFuncCall(StringInfo str, FuncCall *func_call);
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr);
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr);
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize);
+static void deparseConstraint(StringInfo str, Constraint *constraint);
+static void deparseSchemaStmt(StringInfo str, Node *node);
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt);
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition);
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item);
+static void deparseAConst(StringInfo str, A_Const *a_const);
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr);
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func);
+
+static void deparsePreparableStmt(StringInfo str, Node *node);
+static void deparseRuleActionStmt(StringInfo str, Node *node);
+static void deparseExplainableStmt(StringInfo str, Node *node);
+static void deparseStmt(StringInfo str, Node *node);
+static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context);
+
+// "any_name" in gram.y
+static void deparseAnyName(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, parts)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipFirst(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, parts, 1)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipLast(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, parts)
+ {
+ if (lnext(parts, lc))
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (foreach_current_index(lc) < list_length(parts) - 2)
+ appendStringInfoChar(str, '.');
+ }
+ }
+}
+
+// "a_expr" / "b_expr" in gram.y
+static void deparseExpr(StringInfo str, Node *node)
+{
+ if (node == NULL)
+ return;
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Expr:
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_NullTest:
+ deparseNullTest(str, castNode(NullTest, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_BoolExpr:
+ deparseBoolExpr(str, castNode(BoolExpr, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_SetToDefault:
+ deparseSetToDefault(str, castNode(SetToDefault, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CollateClause:
+ deparseCollateClause(str, castNode(CollateClause, node));
+ break;
+ case T_CurrentOfExpr:
+ deparseCurrentOfExpr(str, castNode(CurrentOfExpr, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_BooleanTest:
+ deparseBooleanTest(str, castNode(BooleanTest, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "c_expr" in gram.y
+static void deparseCExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_A_Expr:
+ appendStringInfoChar(str, '(');
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ')');
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in c_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "expr_list" in gram.y
+static void deparseExprList(StringInfo str, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
+static void deparseColId(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "ColLabel", "attr_name"
+//
+// Note this is kept separate from ColId in case we ever want to be more
+// specific on how to handle keywords here
+static void deparseColLabel(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "SignedIconst" and "Iconst" in gram.y
+static void deparseSignedIconst(StringInfo str, Node *node)
+{
+ appendStringInfo(str, "%d", intVal(node));
+}
+
+// "indirection" and "opt_indirection" in gram.y
+static void deparseOptIndirection(StringInfo str, List *indirection, int N)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, indirection, N)
+ {
+ if (IsA(lfirst(lc), String))
+ {
+ appendStringInfoChar(str, '.');
+ deparseColLabel(str, strVal(lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Star))
+ {
+ appendStringInfoString(str, ".*");
+ }
+ else if (IsA(lfirst(lc), A_Indices))
+ {
+ deparseAIndices(str, castNode(A_Indices, lfirst(lc)));
+ }
+ else
+ {
+ // No other nodes should appear here
+ Assert(false);
+ }
+ }
+}
+
+// "role_list" in gram.y
+static void deparseRoleList(StringInfo str, List *roles)
+{
+ ListCell *lc;
+
+ foreach(lc, roles)
+ {
+ RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
+ deparseRoleSpec(str, role_spec);
+ if (lnext(roles, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SimpleTypename" in gram.y
+static void deparseSimpleTypename(StringInfo str, Node *node)
+{
+ deparseTypeName(str, castNode(TypeName, node));
+}
+
+// "NumericOnly" in gram.y
+static void deparseNumericOnly(StringInfo str, Value *value)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ appendStringInfo(str, "%d", value->val.ival);
+ break;
+ case T_Float:
+ appendStringInfoString(str, value->val.str);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "NumericOnly_list" in gram.y
+static void deparseNumericOnlyList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseNumericOnly(str, (Value *) lfirst(lc));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SeqOptElem" in gram.y
+static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseSimpleTypename(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cache") == 0)
+ {
+ appendStringInfoString(str, "CACHE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NO CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "increment") == 0)
+ {
+ appendStringInfoString(str, "INCREMENT ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MAXVALUE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MAXVALUE");
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MINVALUE ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MINVALUE");
+ }
+ else if (strcmp(def_elem->defname, "owned_by") == 0)
+ {
+ appendStringInfoString(str, "OWNED BY ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "sequence_name") == 0)
+ {
+ appendStringInfoString(str, "SEQUENCE NAME ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "start") == 0)
+ {
+ appendStringInfoString(str, "START ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "SeqOptList" in gram.y
+static void deparseSeqOptList(StringInfo str, List *options)
+{
+ ListCell *lc;
+ Assert(list_length(options) > 0);
+ foreach (lc, options)
+ {
+ deparseSeqOptElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "OptSeqOptList" in gram.y
+static void deparseOptSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ deparseSeqOptList(str, options);
+}
+
+// "OptParenthesizedSeqOptList" in gram.y
+static void deparseOptParenthesizedSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseSeqOptList(str, options);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "opt_drop_behavior" in gram.y
+static void deparseOptDropBehavior(StringInfo str, DropBehavior behavior)
+{
+ switch (behavior)
+ {
+ case DROP_RESTRICT:
+ // Default
+ break;
+ case DROP_CASCADE:
+ appendStringInfoString(str, "CASCADE ");
+ break;
+ }
+}
+
+// "any_operator" in gram.y
+static void deparseAnyOperator(StringInfo str, List *op)
+{
+ Assert(isOp(strVal(llast(op))));
+ if (list_length(op) == 2)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(linitial(op))));
+ appendStringInfoChar(str, '.');
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else if (list_length(op) == 1)
+ {
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "qual_Op" and "qual_all_Op" in gram.y
+static void deparseQualOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// "subquery_Op" in gram.y
+static void deparseSubqueryOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
+ {
+ appendStringInfoString(str, "LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
+ {
+ appendStringInfoString(str, "NOT LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
+ {
+ appendStringInfoString(str, "ILIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
+ {
+ appendStringInfoString(str, "NOT ILIKE");
+ }
+ else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// Not present directly in gram.y (usually matched by ColLabel)
+static void deparseGenericDefElemName(StringInfo str, const char *in)
+{
+ Assert(in != NULL);
+ char *val = pstrdup(in);
+ for (unsigned char *p = (unsigned char *) val; *p; p++)
+ *p = pg_toupper(*p);
+ appendStringInfoString(str, val);
+ pfree(val);
+}
+
+// "def_arg" and "operator_def_arg" in gram.y
+static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
+{
+ if (IsA(arg, TypeName)) // func_type
+ {
+ deparseTypeName(str, castNode(TypeName, arg));
+ }
+ else if (IsA(arg, List)) // qual_all_Op
+ {
+ List *l = castNode(List, arg);
+ Assert(list_length(l) == 1 || list_length(l) == 2);
+
+ // Schema qualified operator
+ if (list_length(l) == 2)
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, l);
+ appendStringInfoChar(str, ')');
+ }
+ else if (list_length(l) == 1)
+ {
+ appendStringInfoString(str, strVal(linitial(l)));
+ }
+ }
+ else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
+ {
+ deparseValue(str, (Value *) arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (IsA(arg, String))
+ {
+ char *s = strVal(arg);
+ if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) // NONE
+ {
+ appendStringInfoString(str, "NONE");
+ }
+ else if (isReservedKeyword(s)) // reserved_keyword
+ {
+ appendStringInfoString(str, s);
+ }
+ else // Sconst
+ {
+ deparseStringLiteral(str, s);
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "definition" in gram.y
+static void deparseDefinition(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL) {
+ appendStringInfoString(str, " = ");
+ deparseDefArg(str, def_elem->arg, false);
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "opt_definition" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptDefinition(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseDefinition(str, options);
+ }
+}
+
+// "create_generic_options" in gram.y
+static void deparseCreateGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ if (options == NULL)
+ return;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "common_func_opt_item" in gram.y
+static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "CALLED ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
+ {
+ appendStringInfoString(str, "IMMUTABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
+ {
+ appendStringInfoString(str, "STABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
+ {
+ appendStringInfoString(str, "VOLATILE");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "SECURITY DEFINER");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "SECURITY INVOKER");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOT LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "cost") == 0)
+ {
+ appendStringInfoString(str, "COST ");
+ deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "rows") == 0)
+ {
+ appendStringInfoString(str, "ROWS ");
+ deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "support") == 0)
+ {
+ appendStringInfoString(str, "SUPPORT ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
+ {
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "parallel") == 0)
+ {
+ appendStringInfoString(str, "PARALLEL ");
+ appendStringInfoString(str, quote_identifier(strVal(def_elem->arg)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "NonReservedWord_or_Sconst" in gram.y
+//
+// Note since both identifiers and string constants are allowed here, we
+// currently always return an identifier, except:
+//
+// 1) when the string is empty (since an empty identifier can't be scanned)
+// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
+static void deparseNonReservedWordOrSconst(StringInfo str, const char *val)
+{
+ if (strlen(val) == 0)
+ appendStringInfoString(str, "''");
+ else if (strlen(val) >= NAMEDATALEN)
+ deparseStringLiteral(str, val);
+ else
+ appendStringInfoString(str, quote_identifier(val));
+}
+
+// "func_as" in gram.y
+static void deparseFuncAs(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ char *strval = strVal(lfirst(lc));
+ if (strstr(strval, "$$") == NULL)
+ {
+ appendStringInfoString(str, "$$");
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, "$$");
+ }
+ else
+ {
+ deparseStringLiteral(str, strval);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createfunc_opt_item" in gram.y
+static void deparseCreateFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc = NULL;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseFuncAs(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "transform") == 0)
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, "TRANSFORM ");
+ foreach (lc, l)
+ {
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ else if (strcmp(def_elem->defname, "window") == 0)
+ {
+ appendStringInfoString(str, "WINDOW");
+ }
+ else
+ {
+ deparseCommonFuncOptItem(str, def_elem);
+ }
+}
+
+// "alter_generic_options" in gram.y
+static void deparseAlterGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ switch (def_elem->defaction)
+ {
+ case DEFELEM_UNSPEC:
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ break;
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "func_name" in gram.y
+static void deparseFuncName(StringInfo str, List *func_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, func_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(func_name, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "function_with_argtypes" in gram.y
+static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc;
+ deparseFuncName(str, object_with_args->objname);
+
+ if (!object_with_args->args_unspecified)
+ {
+ appendStringInfoChar(str, '(');
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "function_with_argtypes_list" in gram.y
+static void deparseFunctionWithArgtypesList(StringInfo str, List *l)
+{
+ ListCell *lc;
+
+ foreach(lc, l)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "operator_with_argtypes" in gram.y
+static void deparseOperatorWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ deparseAnyOperator(str, object_with_args->objname);
+
+ Assert(list_length(object_with_args->objargs) == 2);
+ appendStringInfoChar(str, '(');
+ if (linitial(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, linitial(object_with_args->objargs)));
+ appendStringInfoString(str, ", ");
+ if (lsecond(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, lsecond(object_with_args->objargs)));
+ appendStringInfoChar(str, ')');
+}
+
+// "aggr_args" in gram.y
+static void deparseAggrArgs(StringInfo str, List *aggr_args)
+{
+ Assert(list_length(aggr_args) == 2);
+
+ ListCell *lc = NULL;
+ List *args = linitial(aggr_args);
+ int order_by_pos = intVal(lsecond(aggr_args));
+
+ appendStringInfoChar(str, '(');
+ if (args == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, args)
+ {
+ if (foreach_current_index(lc) == order_by_pos)
+ {
+ if (foreach_current_index(lc) > 0)
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, "ORDER BY ");
+ }
+ else if (foreach_current_index(lc) > 0)
+ {
+ appendStringInfoString(str, ", ");
+ }
+
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ }
+
+ // Repeat the last direct arg as a ordered arg to handle the
+ // simplification done by makeOrderedSetArgs in gram.y
+ if (order_by_pos == list_length(args))
+ {
+ appendStringInfoString(str, " ORDER BY ");
+ deparseFunctionParameter(str, castNode(FunctionParameter, llast(args)));
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "aggregate_with_argtypes" in gram.y
+static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc = NULL;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ appendStringInfoChar(str, '(');
+ if (object_with_args->objargs == NULL && object_with_args->objfuncargs == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "columnList" in gram.y
+static void deparseColumnList(StringInfo str, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(columns, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptTemp" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptTemp(StringInfo str, char relpersistence)
+{
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_PERMANENT:
+ // Default
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ appendStringInfoString(str, "UNLOGGED ");
+ break;
+ case RELPERSISTENCE_TEMP:
+ appendStringInfoString(str, "TEMPORARY ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+// "relation_expr_list" in gram.y
+static void deparseRelationExprList(StringInfo str, List *relation_exprs)
+{
+ ListCell *lc = NULL;
+ foreach(lc, relation_exprs)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(relation_exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "handler_name" in gram.y
+static void deparseHandlerName(StringInfo str, List *handler_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, handler_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(handler_name, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "fdw_options" in gram.y
+static void deparseFdwOptions(StringInfo str, List *fdw_options)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, fdw_options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO HANDLER ");
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO VALIDATOR ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(fdw_options, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "type_list" in gram.y
+static void deparseTypeList(StringInfo str, List *type_list)
+{
+ ListCell *lc = NULL;
+ foreach(lc, type_list)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(type_list, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_boolean_or_string" in gram.y
+static void deparseOptBooleanOrString(StringInfo str, char *s)
+{
+ if (s == NULL)
+ return; // No value set
+ else if (strcmp(s, "true") == 0)
+ appendStringInfoString(str, "TRUE");
+ else if (strcmp(s, "false") == 0)
+ appendStringInfoString(str, "FALSE");
+ else if (strcmp(s, "on") == 0)
+ appendStringInfoString(str, "ON");
+ else if (strcmp(s, "off") == 0)
+ appendStringInfoString(str, "OFF");
+ else
+ deparseNonReservedWordOrSconst(str, s);
+}
+
+// "var_name"
+//
+// Note this is kept separate from ColId in case we want to improve the
+// output of namespaced variable names
+static void deparseVarName(StringInfo str, char *s)
+{
+ deparseColId(str, s);
+}
+
+// "var_list"
+static void deparseVarList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, lfirst(lc));
+ if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
+ deparseNumericOnly(str, (Value *) &a_const->val);
+ else if (IsA(&a_const->val, String))
+ deparseOptBooleanOrString(str, strVal(&a_const->val));
+ else
+ Assert(false);
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "transaction_mode_list" in gram.y
+static void deparseTransactionModeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "transaction_isolation") == 0)
+ {
+ char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
+ appendStringInfoString(str, "ISOLATION LEVEL ");
+ if (strcmp(s, "read uncommitted") == 0)
+ appendStringInfoString(str, "READ UNCOMMITTED");
+ else if (strcmp(s, "read committed") == 0)
+ appendStringInfoString(str, "READ COMMITTED");
+ else if (strcmp(s, "repeatable read") == 0)
+ appendStringInfoString(str, "REPEATABLE READ");
+ else if (strcmp(s, "serializable") == 0)
+ appendStringInfoString(str, "SERIALIZABLE");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "READ ONLY");
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "READ WRITE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "DEFERRABLE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "NOT DEFERRABLE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "alter_identity_column_option_list" in gram.y
+static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "generated") == 0)
+ {
+ appendStringInfoString(str, "SET GENERATED ");
+ if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
+ appendStringInfoString(str, "ALWAYS");
+ else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+ appendStringInfoString(str, "BY DEFAULT");
+ else
+ Assert(false);
+ }
+ else
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSeqOptElem(str, def_elem);
+ }
+ if (lnext(l, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "reloptions" in gram.y
+static void deparseRelOptions(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (def_elem->defnamespace != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defnamespace));
+ appendStringInfoChar(str, '.');
+ }
+ if (def_elem->defname != NULL)
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->defname != NULL && def_elem->arg != NULL)
+ appendStringInfoChar(str, '=');
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, false);
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "OptWith" and "opt_reloptions" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptWith(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseRelOptions(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "target_list" and "opt_target_list" in gram.y
+static void deparseTargetList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+
+ if (res_target->val == NULL)
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
+ else if (IsA(res_target->val, ColumnRef))
+ deparseColumnRef(str, castNode(ColumnRef, res_target->val));
+ else
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL) {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "insert_column_list" in gram.y
+static void deparseInsertColumnList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->name != NULL);
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ deparseOptIndirection(str, res_target->indirection, 0);
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_attribute_list" in gram.y
+static void deparseXmlAttributeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_namespace_list" in gram.y
+static void deparseXmlNamespaceList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (res_target->name == NULL)
+ appendStringInfoString(str, "DEFAULT ");
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "table_ref" in gram.y
+static void deparseTableRef(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_RangeVar:
+ deparseRangeVar(str, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_RangeTableSample:
+ deparseRangeTableSample(str, castNode(RangeTableSample, node));
+ break;
+ case T_RangeFunction:
+ deparseRangeFunction(str, castNode(RangeFunction, node));
+ break;
+ case T_RangeTableFunc:
+ deparseRangeTableFunc(str, castNode(RangeTableFunc, node));
+ break;
+ case T_RangeSubselect:
+ deparseRangeSubselect(str, castNode(RangeSubselect, node));
+ break;
+ case T_JoinExpr:
+ deparseJoinExpr(str, castNode(JoinExpr, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "from_list" in gram.y
+static void deparseFromList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseTableRef(str, lfirst(lc));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "from_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseFromClause(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseFromList(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "where_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereClause(StringInfo str, Node *node)
+{
+ if (node != NULL)
+ {
+ appendStringInfoString(str, "WHERE ");
+ deparseExpr(str, node);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "group_by_list" in gram.y
+static void deparseGroupByList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), GroupingSet))
+ deparseGroupingSet(str, castNode(GroupingSet, lfirst(lc)));
+ else
+ deparseExpr(str, lfirst(lc));
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "set_target" in gram.y
+static void deparseSetTarget(StringInfo str, ResTarget *res_target)
+{
+ Assert(res_target->name != NULL);
+ deparseColId(str, res_target->name);
+ deparseOptIndirection(str, res_target->indirection, 0);
+}
+
+// "any_name_list" in gram.y
+static void deparseAnyNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseAnyName(str, castNode(List, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "name_list" in gram.y
+static void deparseNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseColId(str, strVal(lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_sort_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptSortClause(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "ORDER BY ");
+
+ foreach(lc, l)
+ {
+ deparseSortBy(str, castNode(SortBy, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "func_arg_expr" in gram.y
+static void deparseFuncArgExpr(StringInfo str, Node *node)
+{
+ if (IsA(node, NamedArgExpr))
+ {
+ NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
+ appendStringInfoString(str, named_arg_expr->name);
+ appendStringInfoString(str, " := ");
+ deparseExpr(str, (Node *) named_arg_expr->arg);
+ }
+ else
+ {
+ deparseExpr(str, node);
+ }
+}
+
+// "set_clause_list" in gram.y
+static void deparseSetClauseList(StringInfo str, List *target_list)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ int skip_next_n_elems = 0;
+
+ Assert(list_length(target_list) > 0);
+
+ foreach(lc, target_list)
+ {
+ if (skip_next_n_elems > 0)
+ {
+ skip_next_n_elems--;
+ continue;
+ }
+
+ if (foreach_current_index(lc) != 0)
+ appendStringInfoString(str, ", ");
+
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (IsA(res_target->val, MultiAssignRef))
+ {
+ MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
+ appendStringInfoString(str, "(");
+ for_each_cell(lc2, target_list, lc)
+ {
+ deparseSetTarget(str, castNode(ResTarget, lfirst(lc2)));
+ if (foreach_current_index(lc2) == r->ncolumns - 1) // Last element in this multi-assign
+ break;
+ else if (lnext(target_list, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") = ");
+ deparseExpr(str, r->source);
+ skip_next_n_elems = r->ncolumns - 1;
+ }
+ else
+ {
+ deparseSetTarget(str, res_target);
+ appendStringInfoString(str, " = ");
+ deparseExpr(str, res_target->val);
+ }
+ }
+}
+
+// "func_expr_windowless" in gram.y
+static void deparseFuncExprWindowless(StringInfo str, Node* node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "opt_collate" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptCollate(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "index_elem" in gram.y
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem)
+{
+ if (index_elem->name != NULL)
+ {
+ deparseColId(str, index_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (index_elem->expr != NULL)
+ {
+ switch (nodeTag(index_elem->expr))
+ {
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_TypeCast:
+ case T_CoalesceExpr:
+ case T_MinMaxExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ deparseFuncExprWindowless(str, index_elem->expr);
+ break;
+ default:
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, index_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseOptCollate(str, index_elem->collation);
+
+ if (list_length(index_elem->opclass) > 0)
+ {
+ deparseAnyName(str, index_elem->opclass);
+
+ if (list_length(index_elem->opclassopts) > 0)
+ deparseRelOptions(str, index_elem->opclassopts);
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (index_elem->ordering)
+ {
+ case SORTBY_DEFAULT:
+ // Default
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ // Not allowed in CREATE INDEX
+ Assert(false);
+ break;
+ }
+
+ switch (index_elem->nulls_ordering)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ // Default
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+// "qualified_name_list" in gram.y
+static void deparseQualifiedNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptInherit" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptInherit(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "INHERITS (");
+ deparseQualifiedNameList(str, l);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+// "privilege_target" in gram.y
+static void deparsePrivilegeTarget(StringInfo str, GrantTargetType targtype, ObjectType objtype, List *objs)
+{
+ switch (targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "FOREIGN SERVER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyNameList(str, objs);
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnlyList(str, objs);
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "ALL TABLES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "ALL SEQUENCES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "ALL FUNCTIONS IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "ALL PROCEDURES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ALL ROUTINES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_DEFAULTS: // defacl_privilege_target
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLES");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTIONS");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPES");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMAS");
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ }
+}
+
+// "opclass_item_list" in gram.y
+static void deparseOpclassItemList(StringInfo str, List *items)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, items)
+ {
+ deparseCreateOpClassItem(str, castNode(CreateOpClassItem, lfirst(lc)));
+ if (lnext(items, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createdb_opt_list" in gram.y
+static void deparseCreatedbOptList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "connection_limit") == 0)
+ appendStringInfoString(str, "CONNECTION LIMIT");
+ else
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ appendStringInfoString(str, "DEFAULT");
+ else if (IsA(def_elem->arg, Integer))
+ deparseSignedIconst(str, def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+
+ if (lnext(l, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "utility_option_list" in gram.y
+static void deparseUtilityOptionList(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ if (def_elem->arg != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ else
+ Assert(false);
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
+{
+ const ListCell *lc = NULL;
+ const ListCell *lc2 = NULL;
+
+ if (stmt->withClause)
+ {
+ deparseWithClause(str, stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (stmt->op) {
+ case SETOP_NONE:
+ if (list_length(stmt->valuesLists) > 0)
+ {
+ const ListCell *lc;
+ appendStringInfoString(str, "VALUES ");
+
+ foreach(lc, stmt->valuesLists)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, lfirst(lc));
+ appendStringInfoChar(str, ')');
+ if (lnext(stmt->valuesLists, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ }
+
+ appendStringInfoString(str, "SELECT ");
+
+ if (list_length(stmt->targetList) > 0)
+ {
+ if (stmt->distinctClause != NULL)
+ {
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
+ {
+ appendStringInfoString(str, "ON (");
+ deparseExprList(str, stmt->distinctClause);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ deparseTargetList(str, stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->intoClause != NULL)
+ {
+ appendStringInfoString(str, "INTO ");
+ deparseOptTemp(str, stmt->intoClause->rel->relpersistence);
+ deparseIntoClause(str, stmt->intoClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, stmt->fromClause);
+ deparseWhereClause(str, stmt->whereClause);
+
+ if (list_length(stmt->groupClause) > 0)
+ {
+ appendStringInfoString(str, "GROUP BY ");
+ if (stmt->groupDistinct)
+ appendStringInfoString(str, "DISTINCT ");
+ deparseGroupByList(str, stmt->groupClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->havingClause != NULL)
+ {
+ appendStringInfoString(str, "HAVING ");
+ deparseExpr(str, stmt->havingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->windowClause != NULL)
+ {
+ appendStringInfoString(str, "WINDOW ");
+ foreach(lc, stmt->windowClause)
+ {
+ WindowDef *window_def = castNode(WindowDef, lfirst(lc));
+ Assert(window_def->name != NULL);
+ appendStringInfoString(str, window_def->name);
+ appendStringInfoString(str, " AS ");
+ deparseWindowDef(str, window_def);
+ if (lnext(stmt->windowClause, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case SETOP_UNION:
+ case SETOP_INTERSECT:
+ case SETOP_EXCEPT:
+ {
+ bool need_larg_parens =
+ list_length(stmt->larg->sortClause) > 0 ||
+ stmt->larg->limitOffset != NULL ||
+ stmt->larg->limitCount != NULL ||
+ list_length(stmt->larg->lockingClause) > 0 ||
+ stmt->larg->withClause != NULL ||
+ stmt->larg->op != SETOP_NONE;
+ bool need_rarg_parens =
+ list_length(stmt->rarg->sortClause) > 0 ||
+ stmt->rarg->limitOffset != NULL ||
+ stmt->rarg->limitCount != NULL ||
+ list_length(stmt->rarg->lockingClause) > 0 ||
+ stmt->rarg->withClause != NULL ||
+ stmt->rarg->op != SETOP_NONE;
+ if (need_larg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->larg);
+ if (need_larg_parens)
+ appendStringInfoChar(str, ')');
+ switch (stmt->op)
+ {
+ case SETOP_UNION:
+ appendStringInfoString(str, " UNION ");
+ break;
+ case SETOP_INTERSECT:
+ appendStringInfoString(str, " INTERSECT ");
+ break;
+ case SETOP_EXCEPT:
+ appendStringInfoString(str, " EXCEPT ");
+ break;
+ default:
+ Assert(false);
+ }
+ if (stmt->all)
+ appendStringInfoString(str, "ALL ");
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ }
+
+ deparseOptSortClause(str, stmt->sortClause);
+
+ if (stmt->limitCount != NULL)
+ {
+ if (stmt->limitOption == LIMIT_OPTION_COUNT)
+ appendStringInfoString(str, "LIMIT ");
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ appendStringInfoString(str, "FETCH FIRST ");
+
+ if (IsA(stmt->limitCount, A_Const) && IsA(&castNode(A_Const, stmt->limitCount)->val, Null))
+ appendStringInfoString(str, "ALL");
+ else
+ deparseCExpr(str, stmt->limitCount);
+
+ appendStringInfoChar(str, ' ');
+
+ if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ appendStringInfoString(str, "ROWS WITH TIES ");
+ }
+
+ if (stmt->limitOffset != NULL)
+ {
+ appendStringInfoString(str, "OFFSET ");
+ deparseExpr(str, stmt->limitOffset);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(stmt->lockingClause) > 0)
+ {
+ foreach(lc, stmt->lockingClause)
+ {
+ deparseLockingClause(str, castNode(LockingClause, lfirst(lc)));
+ if (lnext(stmt->lockingClause, lc))
+ appendStringInfoString(str, " ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause)
+{
+ ListCell *lc;
+
+ deparseRangeVar(str, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE); /* target relation name */
+
+ if (list_length(into_clause->colNames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, into_clause->colNames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (into_clause->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(into_clause->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptWith(str, into_clause->options);
+
+ switch (into_clause->onCommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (into_clause->tableSpaceName != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(into_clause->tableSpaceName));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context)
+{
+ if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ONLY ");
+
+ if (range_var->catalogname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->catalogname));
+ appendStringInfoChar(str, '.');
+ }
+
+ if (range_var->schemaname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->schemaname));
+ appendStringInfoChar(str, '.');
+ }
+
+ Assert(range_var->relname != NULL);
+ appendStringInfoString(str, quote_identifier(range_var->relname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_var->alias != NULL)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_var->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt)
+{
+ if (raw_stmt->stmt == NULL)
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
+
+ deparseStmt(str, raw_stmt->stmt);
+}
+
+static void deparseAlias(StringInfo str, Alias *alias)
+{
+ appendStringInfoString(str, quote_identifier(alias->aliasname));
+
+ if (list_length(alias->colnames) > 0)
+ {
+ const ListCell *lc = NULL;
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, alias->colnames);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseAConst(StringInfo str, A_Const *a_const)
+{
+ deparseValue(str, &a_const->val, DEPARSE_NODE_CONTEXT_CONSTANT);
+}
+
+static void deparseFuncCall(StringInfo str, FuncCall *func_call)
+{
+ const ListCell *lc = NULL;
+
+ Assert(list_length(func_call->funcname) > 0);
+
+ if (list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "OVERLAY(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PLACING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "substring") == 0)
+ {
+ /*
+ * "SUBSTRING" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.substring)
+ */
+ Assert(list_length(func_call->args) == 2 || list_length(func_call->args) == 3);
+ appendStringInfoString(str, "SUBSTRING(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lsecond(func_call->args));
+ if (list_length(func_call->args) == 3)
+ {
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lthird(func_call->args));
+ }
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "position") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "POSITION" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.position)
+ * Note that the first and second arguments are switched in this format
+ */
+ appendStringInfoString(str, "POSITION(");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " IN ");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 3)
+ {
+ /*
+ * "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "overlay(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " placing ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " from ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "pg_collation_for") == 0 &&
+ list_length(func_call->args) == 1)
+ {
+ /*
+ * "collation for" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "collation for (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "extract") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "EXTRACT" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.extract)
+ */
+ appendStringInfoString(str, "extract (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlaps") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * "OVERLAPS" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlaps)
+ * format: (start_1, end_1) overlaps (start_2, end_2)
+ */
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, ") ");
+
+ appendStringInfoString(str, "overlaps ");
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoString(str, ") ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ (
+ strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0
+ ))
+ {
+ /*
+ * "TRIM " is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.ltrim)
+ * Note that the first and second arguments are switched in this format
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ appendStringInfoString(str, "TRIM (");
+ if (strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0)
+ appendStringInfoString(str, "LEADING ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0)
+ appendStringInfoString(str, "BOTH ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0)
+ appendStringInfoString(str, "TRAILING ");
+
+ if (list_length(func_call->args) == 2)
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "timezone") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "AT TIME ZONE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.timezone)
+ * Note that the arguments are swapped in this case
+ */
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " AT TIME ZONE ");
+ deparseExpr(str, linitial(func_call->args));
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "normalize") == 0)
+ {
+ /*
+ * "NORMALIZE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.normalize)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ appendStringInfoString(str, "normalize (");
+
+ deparseExpr(str, linitial(func_call->args));
+ if (list_length(func_call->args) == 2)
+ {
+ appendStringInfoString(str, ", ");
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "is_normalized") == 0)
+ {
+ /*
+ * "IS NORMALIZED" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.is_normalized)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " IS ");
+ if (list_length(func_call->args) == 2)
+ {
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ appendStringInfoString(str, " NORMALIZED ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "xmlexists") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ appendStringInfoString(str, "xmlexists (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ deparseFuncName(str, func_call->funcname);
+ appendStringInfoChar(str, '(');
+
+ if (func_call->agg_distinct)
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (func_call->agg_star)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (list_length(func_call->args) > 0)
+ {
+ foreach(lc, func_call->args)
+ {
+ if (func_call->func_variadic && !lnext(func_call->args, lc))
+ appendStringInfoString(str, "VARIADIC ");
+ deparseFuncArgExpr(str, lfirst(lc));
+ if (lnext(func_call->args, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (func_call->agg_order != NULL && !func_call->agg_within_group)
+ {
+ deparseOptSortClause(str, func_call->agg_order);
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+
+ if (func_call->agg_order != NULL && func_call->agg_within_group)
+ {
+ appendStringInfoString(str, "WITHIN GROUP (");
+ deparseOptSortClause(str, func_call->agg_order);
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->agg_filter)
+ {
+ appendStringInfoString(str, "FILTER (WHERE ");
+ deparseExpr(str, func_call->agg_filter);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->over)
+ {
+ appendStringInfoString(str, "OVER ");
+ if (func_call->over->name)
+ appendStringInfoString(str, func_call->over->name);
+ else
+ deparseWindowDef(str, func_call->over);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseWindowDef(StringInfo str, WindowDef* window_def)
+{
+ ListCell *lc;
+
+ // The parent node is responsible for outputting window_def->name
+
+ appendStringInfoChar(str, '(');
+
+ if (window_def->refname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(window_def->refname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(window_def->partitionClause) > 0)
+ {
+ appendStringInfoString(str, "PARTITION BY ");
+ deparseExprList(str, window_def->partitionClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptSortClause(str, window_def->orderClause);
+
+ if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
+ {
+ if (window_def->frameOptions & FRAMEOPTION_RANGE)
+ appendStringInfoString(str, "RANGE ");
+ else if (window_def->frameOptions & FRAMEOPTION_ROWS)
+ appendStringInfoString(str, "ROWS ");
+ else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
+ appendStringInfoString(str, "GROUPS ");
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ appendStringInfoString(str, "BETWEEN ");
+
+ // frame_start
+ if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ {
+ appendStringInfoString(str, "UNBOUNDED PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ {
+ appendStringInfoString(str, "AND ");
+
+ // frame_end
+ if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
+ {
+ appendStringInfoString(str, "UNBOUNDED FOLLOWING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
+ appendStringInfoString(str, "EXCLUDE CURRENT ROW ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
+ appendStringInfoString(str, "EXCLUDE GROUP ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
+ appendStringInfoString(str, "EXCLUDE TIES ");
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref)
+{
+ Assert(list_length(column_ref->fields) >= 1);
+
+ if (IsA(linitial(column_ref->fields), A_Star))
+ deparseAStar(str, castNode(A_Star, linitial(column_ref->fields)));
+ else if (IsA(linitial(column_ref->fields), String))
+ deparseColLabel(str, strVal(linitial(column_ref->fields)));
+
+ deparseOptIndirection(str, column_ref->fields, 1);
+}
+
+static void deparseSubLink(StringInfo str, SubLink* sub_link)
+{
+ switch (sub_link->subLinkType) {
+ case EXISTS_SUBLINK:
+ appendStringInfoString(str, "EXISTS (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ALL_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ALL (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ANY_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ if (list_length(sub_link->operName) > 0)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ANY ");
+ }
+ else
+ {
+ appendStringInfoString(str, " IN ");
+ }
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ROWCOMPARE_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case EXPR_SUBLINK:
+ appendStringInfoString(str, "(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case MULTIEXPR_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case ARRAY_SUBLINK:
+ appendStringInfoString(str, "ARRAY(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case CTE_SUBLINK: /* for SubPlans only */
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context)
+{
+ ListCell *lc;
+ char *name;
+
+ bool need_lexpr_parens = a_expr->lexpr != NULL && (IsA(a_expr->lexpr, BoolExpr) || IsA(a_expr->lexpr, NullTest) || IsA(a_expr->lexpr, A_Expr));
+ bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
+
+ switch (a_expr->kind) {
+ case AEXPR_OP: /* normal operator */
+ {
+ bool need_outer_parens = context == DEPARSE_NODE_CONTEXT_A_EXPR;
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, '(');
+ if (a_expr->lexpr != NULL)
+ {
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ deparseQualOp(str, a_expr->name);
+ if (a_expr->rexpr != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ }
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, ')');
+ }
+ return;
+ case AEXPR_OP_ANY: /* scalar op ANY (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ANY(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OP_ALL: /* scalar op ALL (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ALL(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoString(str, " IS DISTINCT FROM ");
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, " IS NOT DISTINCT FROM ");
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_NULLIF: /* NULLIF - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ appendStringInfoString(str, "NULLIF(");
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IN ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "NOT IN ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ if (IsA(a_expr->rexpr, SubLink))
+ deparseSubLink(str, castNode(SubLink, a_expr->rexpr));
+ else
+ deparseExprList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~~") == 0) {
+ appendStringInfoString(str, "LIKE ");
+ } else if (strcmp(name, "!~~") == 0) {
+ appendStringInfoString(str, "NOT LIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~~*") == 0) {
+ appendStringInfoString(str, "ILIKE ");
+ } else if (strcmp(name, "!~~*") == 0) {
+ appendStringInfoString(str, "NOT ILIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((Value *) linitial(a_expr->name))->val.str;
+ if (strcmp(name, "~") == 0) {
+ appendStringInfoString(str, "SIMILAR TO ");
+ } else if (strcmp(name, "!~") == 0) {
+ appendStringInfoString(str, "NOT SIMILAR TO ");
+ } else {
+ Assert(false);
+ }
+
+ FuncCall *n = castNode(FuncCall, a_expr->rexpr);
+ Assert(list_length(n->funcname) == 2);
+ Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
+ Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
+ Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
+
+ deparseExpr(str, linitial(n->args));
+ if (list_length(n->args) == 2)
+ {
+ appendStringInfoString(str, " ESCAPE ");
+ deparseExpr(str, lsecond(n->args));
+ }
+
+ return;
+ case AEXPR_BETWEEN: /* name must be "BETWEEN" */
+ case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
+ case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
+ case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, strVal(linitial(a_expr->name)));
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, castNode(List, a_expr->rexpr)) {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(castNode(List, a_expr->rexpr), lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ }
+}
+
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr)
+{
+ const ListCell *lc = NULL;
+ switch (bool_expr->boolop)
+ {
+ case AND_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(bool_expr->args, lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case OR_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(bool_expr->args, lc))
+ appendStringInfoString(str, " OR ");
+ }
+ return;
+ case NOT_EXPR:
+ Assert(list_length(bool_expr->args) == 1);
+ bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
+ appendStringInfoString(str, "NOT ");
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(bool_expr->args));
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ }
+}
+
+static void deparseAStar(StringInfo str, A_Star *a_star)
+{
+ appendStringInfoChar(str, '*');
+}
+
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause)
+{
+ ListCell *lc;
+ if (collate_clause->arg != NULL)
+ {
+ bool need_parens = IsA(collate_clause->arg, A_Expr);
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, collate_clause->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, collate_clause->collname);
+}
+
+static void deparseSortBy(StringInfo str, SortBy* sort_by)
+{
+ deparseExpr(str, sort_by->node);
+ appendStringInfoChar(str, ' ');
+
+ switch (sort_by->sortby_dir)
+ {
+ case SORTBY_DEFAULT:
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ appendStringInfoString(str, "USING ");
+ deparseQualOp(str, sort_by->useOp);
+ break;
+ }
+
+ switch (sort_by->sortby_nulls)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseParamRef(StringInfo str, ParamRef* param_ref)
+{
+ if (param_ref->number == 0) {
+ appendStringInfoChar(str, '?');
+ } else {
+ appendStringInfo(str, "$%d", param_ref->number);
+ }
+}
+
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function)
+{
+ switch (sql_value_function->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ appendStringInfoString(str, "current_date");
+ break;
+ case SVFOP_CURRENT_TIME:
+ appendStringInfoString(str, "current_time");
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ appendStringInfoString(str, "current_time"); // with precision
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ appendStringInfoString(str, "current_timestamp");
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ appendStringInfoString(str, "current_timestamp"); // with precision
+ break;
+ case SVFOP_LOCALTIME:
+ appendStringInfoString(str, "localtime");
+ break;
+ case SVFOP_LOCALTIME_N:
+ appendStringInfoString(str, "localtime"); // with precision
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ appendStringInfoString(str, "localtimestamp");
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ appendStringInfoString(str, "localtimestamp"); // with precision
+ break;
+ case SVFOP_CURRENT_ROLE:
+ appendStringInfoString(str, "current_role");
+ break;
+ case SVFOP_CURRENT_USER:
+ appendStringInfoString(str, "current_user");
+ break;
+ case SVFOP_USER:
+ appendStringInfoString(str, "user");
+ break;
+ case SVFOP_SESSION_USER:
+ appendStringInfoString(str, "session_user");
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ appendStringInfoString(str, "current_catalog");
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ appendStringInfoString(str, "current_schema");
+ break;
+ }
+
+ if (sql_value_function->typmod != -1)
+ {
+ appendStringInfo(str, "(%d)", sql_value_function->typmod);
+ }
+}
+
+static void deparseWithClause(StringInfo str, WithClause *with_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "WITH ");
+ if (with_clause->recursive)
+ appendStringInfoString(str, "RECURSIVE ");
+
+ foreach(lc, with_clause->ctes) {
+ deparseCommonTableExpr(str, castNode(CommonTableExpr, lfirst(lc)));
+ if (lnext(with_clause->ctes, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
+{
+ ListCell *lc;
+ bool need_alias_parens = join_expr->alias != NULL;
+ bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
+
+ if (need_alias_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseTableRef(str, join_expr->larg);
+
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->isNatural)
+ appendStringInfoString(str, "NATURAL ");
+
+ switch (join_expr->jointype)
+ {
+ case JOIN_INNER: /* matching tuple pairs only */
+ if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
+ appendStringInfoString(str, "CROSS ");
+ break;
+ case JOIN_LEFT: /* pairs + unmatched LHS tuples */
+ appendStringInfoString(str, "LEFT ");
+ break;
+ case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
+ appendStringInfoString(str, "FULL ");
+ break;
+ case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
+ appendStringInfoString(str, "RIGHT ");
+ break;
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ case JOIN_UNIQUE_OUTER:
+ case JOIN_UNIQUE_INNER:
+ // Only used by the planner/executor, not seen in parser output
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "JOIN ");
+
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseTableRef(str, join_expr->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->quals != NULL)
+ {
+ appendStringInfoString(str, "ON ");
+ deparseExpr(str, join_expr->quals);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(join_expr->usingClause) > 0)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseNameList(str, join_expr->usingClause);
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->join_using_alias)
+ {
+ appendStringInfoString(str, "AS ");
+ appendStringInfoString(str, join_expr->join_using_alias->aliasname);
+ }
+ }
+
+ if (need_alias_parens)
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->alias != NULL)
+ deparseAlias(str, join_expr->alias);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCTESearchClause(StringInfo str, CTESearchClause *search_clause)
+{
+ appendStringInfoString(str, " SEARCH ");
+ if (search_clause->search_breadth_first)
+ appendStringInfoString(str, "BREADTH ");
+ else
+ appendStringInfoString(str, "DEPTH ");
+
+ appendStringInfoString(str, "FIRST BY ");
+
+ if (search_clause->search_col_list)
+ deparseColumnList(str, search_clause->search_col_list);
+
+ appendStringInfoString(str, " SET ");
+ appendStringInfoString(str, quote_identifier(search_clause->search_seq_column));
+}
+
+static void deparseCTECycleClause(StringInfo str, CTECycleClause *cycle_clause)
+{
+ appendStringInfoString(str, " CYCLE ");
+
+ if (cycle_clause->cycle_col_list)
+ deparseColumnList(str, cycle_clause->cycle_col_list);
+
+ appendStringInfoString(str, " SET ");
+ appendStringInfoString(str, quote_identifier(cycle_clause->cycle_mark_column));
+
+ if (cycle_clause->cycle_mark_value)
+ {
+ appendStringInfoString(str, " TO ");
+ deparseExpr(str, cycle_clause->cycle_mark_value);
+ }
+
+ if (cycle_clause->cycle_mark_default)
+ {
+ appendStringInfoString(str, " DEFAULT ");
+ deparseExpr(str, cycle_clause->cycle_mark_default);
+ }
+
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(cycle_clause->cycle_path_column));
+}
+
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
+{
+ deparseColId(str, cte->ctename);
+
+ if (list_length(cte->aliascolnames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, cte->aliascolnames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ switch (cte->ctematerialized) {
+ case CTEMaterializeDefault: /* no option specified */
+ break;
+ case CTEMaterializeAlways:
+ appendStringInfoString(str, "MATERIALIZED ");
+ break;
+ case CTEMaterializeNever:
+ appendStringInfoString(str, "NOT MATERIALIZED ");
+ break;
+ }
+
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, cte->ctequery);
+ appendStringInfoChar(str, ')');
+
+ if (cte->search_clause)
+ deparseCTESearchClause(str, cte->search_clause);
+ if (cte->cycle_clause)
+ deparseCTECycleClause(str, cte->cycle_clause);
+}
+
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
+{
+ if (range_subselect->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, range_subselect->subquery));
+ appendStringInfoChar(str, ')');
+
+ if (range_subselect->alias != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseAlias(str, range_subselect->alias);
+ }
+}
+
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (range_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ if (range_func->is_rowsfrom)
+ {
+ appendStringInfoString(str, "ROWS FROM ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->functions)
+ {
+ List *lfunc = castNode(List, lfirst(lc));
+ Assert(list_length(lfunc) == 2);
+ deparseFuncExprWindowless(str, linitial(lfunc));
+ appendStringInfoChar(str, ' ');
+ List *coldeflist = castNode(List, lsecond(lfunc));
+ if (list_length(coldeflist) > 0)
+ {
+ appendStringInfoString(str, "AS (");
+ foreach(lc2, coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc2)));
+ if (lnext(coldeflist, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ if (lnext(range_func->functions, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(list_length(linitial(range_func->functions)) == 2);
+ deparseFuncExprWindowless(str, linitial(linitial(range_func->functions)));
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (range_func->ordinality)
+ appendStringInfoString(str, "WITH ORDINALITY ");
+
+ if (range_func->alias != NULL)
+ {
+ deparseAlias(str, range_func->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(range_func->coldeflist) > 0)
+ {
+ if (range_func->alias == NULL)
+ appendStringInfoString(str, "AS ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(range_func->coldeflist, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr *array_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ARRAY[");
+ deparseExprList(str, array_expr->elements);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
+{
+ ListCell *lc;
+
+ switch (row_expr->row_format)
+ {
+ case COERCE_EXPLICIT_CALL:
+ appendStringInfoString(str, "ROW");
+ break;
+ case COERCE_SQL_SYNTAX:
+ case COERCE_EXPLICIT_CAST:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCE_IMPLICIT_CAST:
+ // No prefix
+ break;
+ }
+
+ appendStringInfoString(str, "(");
+ deparseExprList(str, row_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
+{
+ bool need_parens = false;
+
+ Assert(type_cast->typeName != NULL);
+
+ if (IsA(type_cast->arg, A_Expr))
+ {
+ appendStringInfoString(str, "CAST(");
+ deparseExpr(str, type_cast->arg);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, type_cast->typeName);
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ if (IsA(type_cast->arg, A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, type_cast->arg);
+
+ if (list_length(type_cast->typeName->names) == 2 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
+ {
+ char *typename = strVal(lsecond(type_cast->typeName->names));
+ if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
+ {
+ appendStringInfoString(str, "char ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
+ {
+ /*
+ * Handle "bool" or "false" in the statement, which is represented as a typecast
+ * (other boolean casts should be represented as a cast, i.e. don't need special handling)
+ */
+ char *const_val = strVal(&a_const->val);
+ if (strcmp(const_val, "t") == 0)
+ {
+ appendStringInfoString(str, "true");
+ return;
+ }
+ if (strcmp(const_val, "f") == 0)
+ {
+ appendStringInfoString(str, "false");
+ return;
+ }
+ }
+ }
+
+ // Ensure negative values have wrapping parentheses
+ if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
+ {
+ need_parens = true;
+ }
+
+ if (list_length(type_cast->typeName->names) == 1 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "point") == 0 &&
+ a_const->location > type_cast->typeName->location)
+ {
+ appendStringInfoString(str, " point ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ }
+
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, type_cast->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, "::");
+ deparseTypeName(str, type_cast->typeName);
+}
+
+static void deparseTypeName(StringInfo str, TypeName *type_name)
+{
+ ListCell *lc;
+ bool skip_typmods = false;
+
+ if (type_name->setof)
+ appendStringInfoString(str, "SETOF ");
+
+ if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
+ {
+ const char *name = strVal(lsecond(type_name->names));
+ if (strcmp(name, "bpchar") == 0)
+ {
+ appendStringInfoString(str, "char");
+ }
+ else if (strcmp(name, "varchar") == 0)
+ {
+ appendStringInfoString(str, "varchar");
+ }
+ else if (strcmp(name, "numeric") == 0)
+ {
+ appendStringInfoString(str, "numeric");
+ }
+ else if (strcmp(name, "bool") == 0)
+ {
+ appendStringInfoString(str, "boolean");
+ }
+ else if (strcmp(name, "int2") == 0)
+ {
+ appendStringInfoString(str, "smallint");
+ }
+ else if (strcmp(name, "int4") == 0)
+ {
+ appendStringInfoString(str, "int");
+ }
+ else if (strcmp(name, "int8") == 0)
+ {
+ appendStringInfoString(str, "bigint");
+ }
+ else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
+ {
+ appendStringInfoString(str, "real");
+ }
+ else if (strcmp(name, "float8") == 0)
+ {
+ appendStringInfoString(str, "double precision");
+ }
+ else if (strcmp(name, "time") == 0)
+ {
+ appendStringInfoString(str, "time");
+ }
+ else if (strcmp(name, "timetz") == 0)
+ {
+ appendStringInfoString(str, "time ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "timestamp") == 0)
+ {
+ appendStringInfoString(str, "timestamp");
+ }
+ else if (strcmp(name, "timestamptz") == 0)
+ {
+ appendStringInfoString(str, "timestamp ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
+ {
+ appendStringInfoString(str, "interval");
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
+ {
+ Assert(IsA(linitial(type_name->typmods), A_Const));
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
+
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
+
+ appendStringInfoString(str, "interval");
+
+ // This logic is based on intervaltypmodout in timestamp.c
+ switch (fields)
+ {
+ case INTERVAL_MASK(YEAR):
+ appendStringInfoString(str, " year");
+ break;
+ case INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " month");
+ break;
+ case INTERVAL_MASK(DAY):
+ appendStringInfoString(str, " day");
+ break;
+ case INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " hour");
+ break;
+ case INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " minute");
+ break;
+ case INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " second");
+ break;
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " year to month");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " day to hour");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " day to minute");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " day to second");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " hour to minute");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " hour to second");
+ break;
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " minute to second");
+ break;
+ case INTERVAL_FULL_RANGE:
+ // Nothing
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (list_length(type_name->typmods) == 2)
+ {
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
+ if (precision != INTERVAL_FULL_PRECISION)
+ appendStringInfo(str, "(%d)", precision);
+ }
+
+ skip_typmods = true;
+ }
+ else
+ {
+ appendStringInfoString(str, "pg_catalog.");
+ appendStringInfoString(str, name);
+ }
+ }
+ else
+ {
+ deparseAnyName(str, type_name->names);
+ }
+
+ if (list_length(type_name->typmods) > 0 && !skip_typmods)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ if (IsA(lfirst(lc), A_Const))
+ deparseAConst(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ParamRef))
+ deparseParamRef(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ColumnRef))
+ deparseColumnRef(str, lfirst(lc));
+ else
+ Assert(false);
+
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ foreach(lc, type_name->arrayBounds)
+ {
+ appendStringInfoChar(str, '[');
+ if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
+ deparseSignedIconst(str, lfirst(lc));
+ appendStringInfoChar(str, ']');
+ }
+
+ if (type_name->pct_type)
+ appendStringInfoString(str, "%type");
+}
+
+static void deparseNullTest(StringInfo str, NullTest *null_test)
+{
+ // argisrow is always false in raw parser output
+ Assert(null_test->argisrow == false);
+
+ deparseExpr(str, (Node *) null_test->arg);
+ switch (null_test->nulltesttype)
+ {
+ case IS_NULL:
+ appendStringInfoString(str, " IS NULL");
+ break;
+ case IS_NOT_NULL:
+ appendStringInfoString(str, " IS NOT NULL");
+ break;
+ }
+}
+
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CASE ");
+
+ if (case_expr->arg != NULL)
+ {
+ deparseExpr(str, (Node *) case_expr->arg);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, case_expr->args)
+ {
+ deparseCaseWhen(str, castNode(CaseWhen, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (case_expr->defresult != NULL)
+ {
+ appendStringInfoString(str, "ELSE ");
+ deparseExpr(str, (Node *) case_expr->defresult);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "END");
+}
+
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when)
+{
+ appendStringInfoString(str, "WHEN ");
+ deparseExpr(str, (Node *) case_when->expr);
+ appendStringInfoString(str, " THEN ");
+ deparseExpr(str, (Node *) case_when->result);
+}
+
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection)
+{
+ ListCell *lc;
+ bool need_parens =
+ IsA(a_indirection->arg, A_Indirection) ||
+ IsA(a_indirection->arg, FuncCall) ||
+ IsA(a_indirection->arg, A_Expr) ||
+ IsA(a_indirection->arg, TypeCast) ||
+ IsA(a_indirection->arg, RowExpr) ||
+ (IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices));
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, a_indirection->arg);
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ deparseOptIndirection(str, a_indirection->indirection, 0);
+}
+
+static void deparseAIndices(StringInfo str, A_Indices *a_indices)
+{
+ appendStringInfoChar(str, '[');
+ if (a_indices->lidx != NULL)
+ deparseExpr(str, a_indices->lidx);
+ if (a_indices->is_slice)
+ appendStringInfoChar(str, ':');
+ if (a_indices->uidx != NULL)
+ deparseExpr(str, a_indices->uidx);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr)
+{
+ appendStringInfoString(str, "COALESCE(");
+ deparseExprList(str, coalesce_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr)
+{
+ switch (min_max_expr->op)
+ {
+ case IS_GREATEST:
+ appendStringInfoString(str, "GREATEST(");
+ break;
+ case IS_LEAST:
+ appendStringInfoString(str, "LEAST(");
+ break;
+ }
+ deparseExprList(str, min_max_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test)
+{
+ deparseExpr(str, (Node *) boolean_test->arg);
+ switch (boolean_test->booltesttype)
+ {
+ case IS_TRUE:
+ appendStringInfoString(str, " IS TRUE");
+ break;
+ case IS_NOT_TRUE:
+ appendStringInfoString(str, " IS NOT TRUE");
+ break;
+ case IS_FALSE:
+ appendStringInfoString(str, " IS FALSE");
+ break;
+ case IS_NOT_FALSE:
+ appendStringInfoString(str, " IS NOT FALSE");
+ break;
+ case IS_UNKNOWN:
+ appendStringInfoString(str, " IS UNKNOWN");
+ break;
+ case IS_NOT_UNKNOWN:
+ appendStringInfoString(str, " IS NOT UNKNOWN");
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
+{
+ ListCell *lc;
+
+ if (column_def->colname != NULL)
+ {
+ appendStringInfoString(str, column_def->colname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->typeName != NULL)
+ {
+ deparseTypeName(str, column_def->typeName);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->raw_default != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseExpr(str, column_def->raw_default);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->fdwoptions != NULL)
+ {
+ deparseCreateGenericOptions(str, column_def->fdwoptions);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, column_def->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->collClause != NULL)
+ {
+ deparseCollateClause(str, column_def->collClause);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (insert_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, insert_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "INSERT INTO ");
+ deparseRangeVar(str, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(insert_stmt->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseInsertColumnList(str, insert_stmt->cols);
+ appendStringInfoString(str, ") ");
+ }
+
+ switch (insert_stmt->override)
+ {
+ case OVERRIDING_NOT_SET:
+ // Do nothing
+ break;
+ case OVERRIDING_USER_VALUE:
+ appendStringInfoString(str, "OVERRIDING USER VALUE ");
+ break;
+ case OVERRIDING_SYSTEM_VALUE:
+ appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
+ break;
+ }
+
+ if (insert_stmt->selectStmt != NULL)
+ {
+ deparseSelectStmt(str, castNode(SelectStmt, insert_stmt->selectStmt));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "DEFAULT VALUES ");
+ }
+
+ if (insert_stmt->onConflictClause != NULL)
+ {
+ deparseOnConflictClause(str, insert_stmt->onConflictClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(insert_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, insert_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInferClause(StringInfo str, InferClause *infer_clause)
+{
+ ListCell *lc;
+
+ if (list_length(infer_clause->indexElems) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, infer_clause->indexElems)
+ {
+ deparseIndexElem(str, lfirst(lc));
+ if (lnext(infer_clause->indexElems, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ if (infer_clause->conname != NULL)
+ {
+ appendStringInfoString(str, "ON CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(infer_clause->conname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, infer_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ON CONFLICT ");
+
+ if (on_conflict_clause->infer != NULL)
+ {
+ deparseInferClause(str, on_conflict_clause->infer);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (on_conflict_clause->action)
+ {
+ case ONCONFLICT_NONE:
+ Assert(false);
+ break;
+ case ONCONFLICT_NOTHING:
+ appendStringInfoString(str, "DO NOTHING ");
+ break;
+ case ONCONFLICT_UPDATE:
+ appendStringInfoString(str, "DO UPDATE ");
+ break;
+ }
+
+ if (list_length(on_conflict_clause->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, on_conflict_clause->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, on_conflict_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
+{
+ ListCell* lc;
+ ListCell* lc2;
+ ListCell* lc3;
+
+ if (update_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, update_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "UPDATE ");
+ deparseRangeVar(str, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(update_stmt->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, update_stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, update_stmt->fromClause);
+ deparseWhereClause(str, update_stmt->whereClause);
+
+ if (list_length(update_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, update_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
+{
+ if (delete_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, delete_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "DELETE FROM ");
+ deparseRangeVar(str, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (delete_stmt->usingClause != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseFromList(str, delete_stmt->usingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, delete_stmt->whereClause);
+
+ if (list_length(delete_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, delete_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause)
+{
+ ListCell *lc;
+
+ switch (locking_clause->strength)
+ {
+ case LCS_NONE:
+ /* no such clause - only used in PlanRowMark */
+ Assert(false);
+ break;
+ case LCS_FORKEYSHARE:
+ appendStringInfoString(str, "FOR KEY SHARE ");
+ break;
+ case LCS_FORSHARE:
+ appendStringInfoString(str, "FOR SHARE ");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ appendStringInfoString(str, "FOR NO KEY UPDATE ");
+ break;
+ case LCS_FORUPDATE:
+ appendStringInfoString(str, "FOR UPDATE ");
+ break;
+ }
+
+ if (list_length(locking_clause->lockedRels) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseQualifiedNameList(str, locking_clause->lockedRels);
+ }
+
+ switch (locking_clause->waitPolicy)
+ {
+ case LockWaitError:
+ appendStringInfoString(str, "NOWAIT");
+ break;
+ case LockWaitSkip:
+ appendStringInfoString(str, "SKIP LOCKED");
+ break;
+ case LockWaitBlock:
+ // Default
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default)
+{
+ appendStringInfoString(str, "DEFAULT");
+}
+
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ appendStringInfoString(str, "CREATE CAST (");
+ deparseTypeName(str, create_cast_stmt->sourcetype);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, create_cast_stmt->targettype);
+ appendStringInfoString(str, ") ");
+
+ if (create_cast_stmt->func != NULL)
+ {
+ appendStringInfoString(str, "WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_cast_stmt->func);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_cast_stmt->inout)
+ {
+ appendStringInfoString(str, "WITH INOUT ");
+ }
+ else
+ {
+ appendStringInfoString(str, "WITHOUT FUNCTION ");
+ }
+
+ switch (create_cast_stmt->context)
+ {
+ case COERCION_IMPLICIT:
+ appendStringInfoString(str, "AS IMPLICIT");
+ break;
+ case COERCION_ASSIGNMENT:
+ appendStringInfoString(str, "AS ASSIGNMENT");
+ break;
+ case COERCION_PLPGSQL:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCION_EXPLICIT:
+ // Default
+ break;
+ }
+}
+
+static void deparseCreateOpClassStmt(StringInfo str, CreateOpClassStmt *create_op_class_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE OPERATOR CLASS ");
+
+ deparseAnyName(str, create_op_class_stmt->opclassname);
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->isDefault)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, create_op_class_stmt->datatype);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_class_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->opfamilyname != NULL)
+ {
+ appendStringInfoString(str, "FAMILY ");
+ deparseAnyName(str, create_op_class_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "AS ");
+ deparseOpclassItemList(str, create_op_class_stmt->items);
+}
+
+static void deparseCreateOpFamilyStmt(StringInfo str, CreateOpFamilyStmt *create_op_family_stmt)
+{
+ appendStringInfoString(str, "CREATE OPERATOR FAMILY ");
+
+ deparseAnyName(str, create_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_family_stmt->amname));
+}
+
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item)
+{
+ ListCell *lc = NULL;
+
+ switch (create_op_class_item->itemtype)
+ {
+ case OPCLASS_ITEM_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+
+ if (create_op_class_item->name != NULL)
+ {
+ if (create_op_class_item->name->objargs != NULL)
+ deparseOperatorWithArgtypes(str, create_op_class_item->name);
+ else
+ deparseAnyOperator(str, create_op_class_item->name->objname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_op_class_item->order_family != NULL)
+ {
+ appendStringInfoString(str, "FOR ORDER BY ");
+ deparseAnyName(str, create_op_class_item->order_family);
+ }
+
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoChar(str, ')');
+ }
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoString(str, ") ");
+ }
+ if (create_op_class_item->name != NULL)
+ deparseFunctionWithArgtypes(str, create_op_class_item->name);
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_STORAGETYPE:
+ appendStringInfoString(str, "STORAGE ");
+ deparseTypeName(str, create_op_class_item->storedtype);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseTableLikeClause(StringInfo str, TableLikeClause *table_like_clause)
+{
+ appendStringInfoString(str, "LIKE ");
+ deparseRangeVar(str, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
+ appendStringInfoString(str, "INCLUDING ALL ");
+ else
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+ appendStringInfoString(str, "INCLUDING COMMENTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ appendStringInfoString(str, "INCLUDING CONSTRAINTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
+ appendStringInfoString(str, "INCLUDING DEFAULTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
+ appendStringInfoString(str, "INCLUDING IDENTITY ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED)
+ appendStringInfoString(str, "INCLUDING GENERATED ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ appendStringInfoString(str, "INCLUDING INDEXES ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
+ appendStringInfoString(str, "INCLUDING STATISTICS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ appendStringInfoString(str, "INCLUDING STORAGE ");
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt)
+{
+ ListCell *lc;
+
+ Assert(create_domain_stmt->typeName != NULL);
+
+ appendStringInfoString(str, "CREATE DOMAIN ");
+ deparseAnyName(str, create_domain_stmt->domainname);
+ appendStringInfoString(str, " AS ");
+
+ deparseTypeName(str, create_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (create_domain_stmt->collClause != NULL)
+ {
+ deparseCollateClause(str, create_domain_stmt->collClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_domain_stmt->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateExtensionStmt(StringInfo str, CreateExtensionStmt *create_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE EXTENSION ");
+
+ if (create_extension_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseColId(str, create_extension_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, create_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "schema") == 0)
+ {
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "cascade") == 0)
+ {
+ appendStringInfoString(str, "CASCADE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraint(StringInfo str, Constraint *constraint)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, constraint->conname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (constraint->contype) {
+ case CONSTR_NULL:
+ appendStringInfoString(str, "NULL ");
+ break;
+ case CONSTR_NOTNULL:
+ appendStringInfoString(str, "NOT NULL ");
+ break;
+ case CONSTR_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, constraint->raw_expr);
+ break;
+ case CONSTR_IDENTITY:
+ appendStringInfoString(str, "GENERATED ");
+ switch (constraint->generated_when)
+ {
+ case ATTRIBUTE_IDENTITY_ALWAYS:
+ appendStringInfoString(str, "ALWAYS ");
+ break;
+ case ATTRIBUTE_IDENTITY_BY_DEFAULT:
+ appendStringInfoString(str, "BY DEFAULT ");
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoString(str, "AS IDENTITY ");
+ deparseOptParenthesizedSeqOptList(str, constraint->options);
+ break;
+ case CONSTR_GENERATED:
+ Assert(constraint->generated_when == ATTRIBUTE_IDENTITY_ALWAYS);
+ appendStringInfoString(str, "GENERATED ALWAYS AS (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") STORED ");
+ break;
+ case CONSTR_CHECK:
+ appendStringInfoString(str, "CHECK (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") ");
+ break;
+ case CONSTR_PRIMARY:
+ appendStringInfoString(str, "PRIMARY KEY ");
+ break;
+ case CONSTR_UNIQUE:
+ appendStringInfoString(str, "UNIQUE ");
+ break;
+ case CONSTR_EXCLUSION:
+ appendStringInfoString(str, "EXCLUDE ");
+ if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(constraint->access_method));
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoChar(str, '(');
+ foreach(lc, constraint->exclusions)
+ {
+ List *exclusion = castNode(List, lfirst(lc));
+ Assert(list_length(exclusion) == 2);
+ deparseIndexElem(str, castNode(IndexElem, linitial(exclusion)));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyOperator(str, castNode(List, lsecond(exclusion)));
+ if (lnext(constraint->exclusions, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ if (constraint->where_clause != NULL)
+ {
+ appendStringInfoString(str, "WHERE (");
+ deparseExpr(str, constraint->where_clause);
+ appendStringInfoString(str, ") ");
+ }
+ break;
+ case CONSTR_FOREIGN:
+ if (list_length(constraint->fk_attrs) > 0)
+ appendStringInfoString(str, "FOREIGN KEY ");
+ break;
+ case CONSTR_ATTR_DEFERRABLE:
+ appendStringInfoString(str, "DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ appendStringInfoString(str, "NOT DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_DEFERRED:
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+ break;
+ case CONSTR_ATTR_IMMEDIATE:
+ appendStringInfoString(str, "INITIALLY IMMEDIATE ");
+ break;
+ }
+
+ if (list_length(constraint->keys) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->keys);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (list_length(constraint->fk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->fk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->pktable != NULL)
+ {
+ appendStringInfoString(str, "REFERENCES ");
+ deparseRangeVar(str, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ if (list_length(constraint->pk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->pk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ switch (constraint->fk_matchtype)
+ {
+ case FKCONSTR_MATCH_SIMPLE:
+ // Default
+ break;
+ case FKCONSTR_MATCH_FULL:
+ appendStringInfoString(str, "MATCH FULL ");
+ break;
+ case FKCONSTR_MATCH_PARTIAL:
+ // Not implemented in Postgres
+ Assert(false);
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_upd_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON UPDATE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON UPDATE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON UPDATE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON UPDATE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_del_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON DELETE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON DELETE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON DELETE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON DELETE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ if (list_length(constraint->including) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ deparseColumnList(str, constraint->including);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->indexname != NULL)
+ appendStringInfo(str, "USING INDEX %s ", quote_identifier(constraint->indexname));
+
+ if (constraint->indexspace != NULL)
+ appendStringInfo(str, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
+
+ if (constraint->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (constraint->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (constraint->is_no_inherit)
+ appendStringInfoString(str, "NO INHERIT ");
+
+ if (constraint->skip_validation)
+ appendStringInfoString(str, "NOT VALID ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReturnStmt(StringInfo str, ReturnStmt *return_stmt)
+{
+ appendStringInfoString(str, "RETURN ");
+ deparseExpr(str, return_stmt->returnval);
+}
+
+static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
+{
+ ListCell *lc;
+ bool tableFunc = false;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_function_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_function_stmt->is_procedure)
+ appendStringInfoString(str, "PROCEDURE ");
+ else
+ appendStringInfoString(str, "FUNCTION ");
+
+ deparseFuncName(str, create_function_stmt->funcname);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode != FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc) && castNode(FunctionParameter, lfirst(lnext(create_function_stmt->parameters, lc)))->mode != FUNC_PARAM_TABLE)
+ appendStringInfoString(str, ", ");
+ }
+ else
+ {
+ tableFunc = true;
+ }
+ }
+ appendStringInfoString(str, ") ");
+
+ if (tableFunc)
+ {
+ appendStringInfoString(str, "RETURNS TABLE (");
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode == FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_function_stmt->returnType != NULL)
+ {
+ appendStringInfoString(str, "RETURNS ");
+ deparseTypeName(str, create_function_stmt->returnType);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_function_stmt->options)
+ {
+ deparseCreateFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_function_stmt->sql_body)
+ {
+ /* RETURN or BEGIN ... END
+ */
+ if (IsA(create_function_stmt->sql_body, ReturnStmt))
+ deparseReturnStmt(str, castNode(ReturnStmt, create_function_stmt->sql_body));
+ else
+ {
+ appendStringInfoString(str, "BEGIN ATOMIC ");
+ deparseExprList(str, castNode(List, create_function_stmt->sql_body));
+ appendStringInfoString(str, "END ");
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter)
+{
+ switch (function_parameter->mode)
+ {
+ case FUNC_PARAM_IN: /* input only */
+ appendStringInfoString(str, "IN ");
+ break;
+ case FUNC_PARAM_OUT: /* output only */
+ appendStringInfoString(str, "OUT ");
+ break;
+ case FUNC_PARAM_INOUT: /* both */
+ appendStringInfoString(str, "INOUT ");
+ break;
+ case FUNC_PARAM_VARIADIC: /* variadic (always input) */
+ appendStringInfoString(str, "VARIADIC ");
+ break;
+ case FUNC_PARAM_TABLE: /* table function output column */
+ // No special annotation, the caller is expected to correctly put
+ // this into the RETURNS part of the CREATE FUNCTION statement
+ break;
+ case FUNC_PARAM_DEFAULT:
+ // Default
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (function_parameter->name != NULL)
+ {
+ appendStringInfoString(str, function_parameter->name);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseTypeName(str, function_parameter->argType);
+ appendStringInfoChar(str, ' ');
+
+ if (function_parameter->defexpr != NULL)
+ {
+ appendStringInfoString(str, "= ");
+ deparseExpr(str, function_parameter->defexpr);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_stmt)
+{
+ appendStringInfoString(str, "CHECKPOINT");
+}
+
+static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE SCHEMA ");
+
+ if (create_schema_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (create_schema_stmt->schemaname)
+ {
+ deparseColId(str, create_schema_stmt->schemaname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->authrole != NULL)
+ {
+ appendStringInfoString(str, "AUTHORIZATION ");
+ deparseRoleSpec(str, create_schema_stmt->authrole);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->schemaElts)
+ {
+ foreach(lc, create_schema_stmt->schemaElts)
+ {
+ deparseSchemaStmt(str, lfirst(lc));
+ if (lnext(create_schema_stmt->schemaElts, lc))
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleSetStmt(StringInfo str, AlterRoleSetStmt *alter_role_set_stmt)
+{
+ appendStringInfoString(str, "ALTER ROLE ");
+
+ if (alter_role_set_stmt->role == NULL)
+ appendStringInfoString(str, "ALL");
+ else
+ deparseRoleSpec(str, alter_role_set_stmt->role);
+
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_set_stmt->database != NULL)
+ {
+ appendStringInfoString(str, "IN DATABASE ");
+ appendStringInfoString(str, quote_identifier(alter_role_set_stmt->database));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseVariableSetStmt(str, alter_role_set_stmt->setstmt);
+}
+
+static void deparseCreateConversionStmt(StringInfo str, CreateConversionStmt *create_conversion_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_conversion_stmt->def)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, create_conversion_stmt->conversion_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "FOR ");
+ deparseStringLiteral(str, create_conversion_stmt->for_encoding_name);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, create_conversion_stmt->to_encoding_name);
+
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, create_conversion_stmt->func_name);
+}
+
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
+{
+ switch (role_spec->roletype)
+ {
+ case ROLESPEC_CSTRING:
+ Assert(role_spec->rolename != NULL);
+ appendStringInfoString(str, quote_identifier(role_spec->rolename));
+ break;
+ case ROLESPEC_CURRENT_ROLE:
+ appendStringInfoString(str, "CURRENT_ROLE");
+ break;
+ case ROLESPEC_CURRENT_USER:
+ appendStringInfoString(str, "CURRENT_USER");
+ break;
+ case ROLESPEC_SESSION_USER:
+ appendStringInfoString(str, "SESSION_USER");
+ break;
+ case ROLESPEC_PUBLIC:
+ appendStringInfoString(str, "public");
+ break;
+ }
+}
+
+// "part_elem" in gram.y
+static void deparsePartitionElem(StringInfo str, PartitionElem *partition_elem)
+{
+ ListCell *lc;
+
+ if (partition_elem->name != NULL)
+ {
+ deparseColId(str, partition_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (partition_elem->expr != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, partition_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptCollate(str, partition_elem->collation);
+ deparseAnyName(str, partition_elem->opclass);
+
+ removeTrailingSpace(str);
+}
+
+static void deparsePartitionSpec(StringInfo str, PartitionSpec *partition_spec)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "PARTITION BY ");
+ appendStringInfoString(str, partition_spec->strategy);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, partition_spec->partParams)
+ {
+ deparsePartitionElem(str, castNode(PartitionElem, lfirst(lc)));
+ if (lnext(partition_spec->partParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparsePartitionBoundSpec(StringInfo str, PartitionBoundSpec *partition_bound_spec)
+{
+ ListCell *lc;
+
+ if (partition_bound_spec->is_default)
+ {
+ appendStringInfoString(str, "DEFAULT");
+ return;
+ }
+
+ appendStringInfoString(str, "FOR VALUES ");
+
+ switch (partition_bound_spec->strategy)
+ {
+ case PARTITION_STRATEGY_HASH:
+ appendStringInfo(str, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
+ break;
+ case PARTITION_STRATEGY_LIST:
+ appendStringInfoString(str, "IN (");
+ deparseExprList(str, partition_bound_spec->listdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ appendStringInfoString(str, "FROM (");
+ deparseExprList(str, partition_bound_spec->lowerdatums);
+ appendStringInfoString(str, ") TO (");
+ deparseExprList(str, partition_bound_spec->upperdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
+{
+ deparseRangeVar(str, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (partition_cmd->bound != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparsePartitionBoundSpec(str, partition_cmd->bound);
+ }
+ if (partition_cmd->concurrent)
+ appendStringInfoString(str, " CONCURRENTLY ");
+}
+
+// "TableElement" in gram.y
+static void deparseTableElement(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnDef:
+ deparseColumnDef(str, castNode(ColumnDef, node));
+ break;
+ case T_TableLikeClause:
+ deparseTableLikeClause(str, castNode(TableLikeClause, node));
+ break;
+ case T_Constraint:
+ deparseConstraint(str, castNode(Constraint, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseCreateStmt(StringInfo str, CreateStmt *create_stmt, bool is_foreign_table)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (is_foreign_table)
+ appendStringInfoString(str, "FOREIGN ");
+
+ deparseOptTemp(str, create_stmt->relation->relpersistence);
+
+ appendStringInfoString(str, "TABLE ");
+
+ if (create_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_stmt->ofTypename != NULL)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseTypeName(str, create_stmt->ofTypename);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ Assert(list_length(create_stmt->inhRelations) == 1);
+ appendStringInfoString(str, "PARTITION OF ");
+ deparseRangeVar(str, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(create_stmt->tableElts) > 0)
+ {
+ // In raw parse output tableElts contains both columns and constraints
+ // (and the constraints field is NIL)
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_stmt->tableElts)
+ {
+ deparseTableElement(str, lfirst(lc));
+ if (lnext(create_stmt->tableElts, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
+ {
+ appendStringInfoString(str, "() ");
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ deparsePartitionBoundSpec(str, create_stmt->partbound);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ deparseOptInherit(str, create_stmt->inhRelations);
+ }
+
+ if (create_stmt->partspec != NULL)
+ {
+ deparsePartitionSpec(str, create_stmt->partspec);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_stmt->accessMethod));
+ }
+
+ deparseOptWith(str, create_stmt->options);
+
+ switch (create_stmt->oncommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No ON COMMIT clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (create_stmt->tablespacename != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(create_stmt->tablespacename));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFdwStmt(StringInfo str, CreateFdwStmt *create_fdw_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, create_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseCreateGenericOptions(str, create_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFdwStmt(StringInfo str, AlterFdwStmt *alter_fdw_stmt)
+{
+ appendStringInfoString(str, "ALTER FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(alter_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, alter_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_fdw_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateForeignServerStmt(StringInfo str, CreateForeignServerStmt *create_foreign_server_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SERVER ");
+ if (create_foreign_server_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (create_foreign_server_stmt->servertype != NULL)
+ {
+ appendStringInfoString(str, "TYPE ");
+ deparseStringLiteral(str, create_foreign_server_stmt->servertype);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_foreign_server_stmt->version != NULL)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseStringLiteral(str, create_foreign_server_stmt->version);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterForeignServerStmt(StringInfo str, AlterForeignServerStmt *alter_foreign_server_stmt)
+{
+ appendStringInfoString(str, "ALTER SERVER ");
+
+ appendStringInfoString(str, quote_identifier(alter_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_foreign_server_stmt->has_version)
+ {
+ appendStringInfoString(str, "VERSION ");
+ if (alter_foreign_server_stmt->version != NULL)
+ deparseStringLiteral(str, alter_foreign_server_stmt->version);
+ else
+ appendStringInfoString(str, "NULL");
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_foreign_server_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateUserMappingStmt(StringInfo str, CreateUserMappingStmt *create_user_mapping_stmt)
+{
+ appendStringInfoString(str, "CREATE USER MAPPING ");
+ if (create_user_mapping_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, create_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(create_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreatedbStmt(StringInfo str, CreatedbStmt *createdb_stmt)
+{
+ appendStringInfoString(str, "CREATE DATABASE ");
+ deparseColId(str, createdb_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, createdb_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterUserMappingStmt(StringInfo str, AlterUserMappingStmt *alter_user_mapping_stmt)
+{
+ appendStringInfoString(str, "ALTER USER MAPPING FOR ");
+ deparseRoleSpec(str, alter_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(alter_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseAlterGenericOptions(str, alter_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropUserMappingStmt(StringInfo str, DropUserMappingStmt *drop_user_mapping_stmt)
+{
+ appendStringInfoString(str, "DROP USER MAPPING ");
+
+ if (drop_user_mapping_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, drop_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(drop_user_mapping_stmt->servername));
+}
+
+static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "SECURITY LABEL ");
+
+ if (sec_label_stmt->provider != NULL)
+ {
+ appendStringInfoString(str, "FOR ");
+ appendStringInfoString(str, quote_identifier(sec_label_stmt->provider));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ switch (sec_label_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseValue(str, (Value *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ default:
+ // Not supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (sec_label_stmt->label != NULL)
+ deparseStringLiteral(str, sec_label_stmt->label);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateForeignTableStmt(StringInfo str, CreateForeignTableStmt *create_foreign_table_stmt)
+{
+ ListCell *lc;
+
+ deparseCreateStmt(str, &create_foreign_table_stmt->base, true);
+
+ appendStringInfoString(str, " SERVER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_table_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_foreign_table_stmt->options) > 0)
+ deparseAlterGenericOptions(str, create_foreign_table_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseImportForeignSchemaStmt(StringInfo str, ImportForeignSchemaStmt *import_foreign_schema_stmt)
+{
+ appendStringInfoString(str, "IMPORT FOREIGN SCHEMA ");
+
+ appendStringInfoString(str, import_foreign_schema_stmt->remote_schema);
+ appendStringInfoChar(str, ' ');
+
+ switch (import_foreign_schema_stmt->list_type)
+ {
+ case FDW_IMPORT_SCHEMA_ALL:
+ // Default
+ break;
+ case FDW_IMPORT_SCHEMA_LIMIT_TO:
+ appendStringInfoString(str, "LIMIT TO (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ case FDW_IMPORT_SCHEMA_EXCEPT:
+ appendStringInfoString(str, "EXCEPT (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ }
+
+ appendStringInfoString(str, "FROM SERVER ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->server_name));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "INTO ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->local_schema));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, import_foreign_schema_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_table_as_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
+
+ switch (create_table_as_stmt->objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ if (create_table_as_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseIntoClause(str, create_table_as_stmt->into);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ if (IsA(create_table_as_stmt->query, ExecuteStmt))
+ deparseExecuteStmt(str, castNode(ExecuteStmt, create_table_as_stmt->query));
+ else
+ deparseSelectStmt(str, castNode(SelectStmt, create_table_as_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_as_stmt->into->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (view_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ deparseOptTemp(str, view_stmt->view->relpersistence);
+
+ appendStringInfoString(str, "VIEW ");
+ deparseRangeVar(str, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(view_stmt->aliases) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, view_stmt->aliases);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, view_stmt->options);
+
+ appendStringInfoString(str, "AS ");
+ deparseSelectStmt(str, castNode(SelectStmt, view_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ switch (view_stmt->withCheckOption)
+ {
+ case NO_CHECK_OPTION:
+ // Default
+ break;
+ case LOCAL_CHECK_OPTION:
+ appendStringInfoString(str, "WITH LOCAL CHECK OPTION ");
+ break;
+ case CASCADED_CHECK_OPTION:
+ appendStringInfoString(str, "WITH CHECK OPTION ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "DROP ");
+
+ switch (drop_stmt->removeType)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ default:
+ // Other object types are not supported here in the parser
+ Assert(false);
+ }
+
+ if (drop_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (drop_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (drop_stmt->removeType)
+ {
+ // drop_type_any_name
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ deparseAnyNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name_on_any_name
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseColId(str, strVal(llast(l)));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_CAST:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TRANSFORM:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_LANGUAGE:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_AGGREGATE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPERATOR:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseOptDropBehavior(str, drop_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set)
+{
+ switch(grouping_set->kind)
+ {
+ case GROUPING_SET_EMPTY:
+ appendStringInfoString(str, "()");
+ break;
+ case GROUPING_SET_SIMPLE:
+ // Not present in raw parse trees
+ Assert(false);
+ break;
+ case GROUPING_SET_ROLLUP:
+ appendStringInfoString(str, "ROLLUP (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_CUBE:
+ appendStringInfoString(str, "CUBE (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_SETS:
+ appendStringInfoString(str, "GROUPING SETS (");
+ deparseGroupByList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ }
+}
+
+static void deparseDropTableSpaceStmt(StringInfo str, DropTableSpaceStmt *drop_table_space_stmt)
+{
+ appendStringInfoString(str, "DROP TABLESPACE ");
+
+ if (drop_table_space_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_table_space_stmt->tablespacename);
+}
+
+static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt *alter_object_depends_stmt)
+{
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_depends_stmt->objectType)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ deparseColId(str, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ // No other object types supported here
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (alter_object_depends_stmt->remove)
+ appendStringInfoString(str, "NO ");
+
+ appendStringInfoString(str, "DEPENDS ON EXTENSION ");
+ deparseColId(str, strVal(alter_object_depends_stmt->extname));
+}
+
+static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
+{
+ List *l = NULL;
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_schema_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ appendStringInfoString(str, quote_identifier(strVal(alter_object_schema_stmt->object)));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " SET SCHEMA ");
+ appendStringInfoString(str, quote_identifier(alter_object_schema_stmt->newschema));
+}
+
+static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+ const char *options = NULL;
+ bool trailing_missing_ok = false;
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AddColumn: /* add column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ADD ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ADD COLUMN ");
+ break;
+ case AT_AddColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_ColumnDefault: /* alter column default */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ if (alter_table_cmd->def != NULL)
+ options = "SET DEFAULT";
+ else
+ options = "DROP DEFAULT";
+ break;
+ case AT_CookedColumnDefault: /* add a pre-cooked column default */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropNotNull: /* alter column drop not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP NOT NULL";
+ break;
+ case AT_SetNotNull: /* alter column set not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET NOT NULL";
+ break;
+ case AT_DropExpression: /* alter column drop expression */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP EXPRESSION";
+ trailing_missing_ok = true;
+ break;
+ case AT_CheckNotNull: /* check column is already marked not null */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_SetStatistics: /* alter column set statistics */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STATISTICS";
+ break;
+ case AT_SetOptions: /* alter column set ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET";
+ break;
+ case AT_ResetOptions: /* alter column reset ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "RESET";
+ break;
+ case AT_SetStorage: /* alter column set storage */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STORAGE";
+ break;
+ case AT_SetCompression: /* alter column set compression */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET COMPRESSION";
+ break;
+ case AT_DropColumn: /* drop column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "DROP ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "DROP ");
+ break;
+ case AT_DropColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndex: /* add index */
+ appendStringInfoString(str, "ADD INDEX ");
+ break;
+ case AT_ReAddIndex: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddConstraint: /* add constraint */
+ appendStringInfoString(str, "ADD ");
+ break;
+ case AT_AddConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterConstraint: /* alter constraint */
+ appendStringInfoString(str, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
+ break;
+ case AT_ValidateConstraint: /* validate constraint */
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ break;
+ case AT_ValidateConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndexConstraint: /* add constraint using existing index */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropConstraint: /* drop constraint */
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ break;
+ case AT_DropConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddComment: /* internal to commands/tablecmds.c */
+ case AT_ReAddStatistics: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterColumnType: /* alter column type */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ALTER ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "TYPE";
+ break;
+ case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ // Handled via special case in def handling
+ break;
+ case AT_ChangeOwner: /* change owner */
+ appendStringInfoString(str, "OWNER TO ");
+ deparseRoleSpec(str, alter_table_cmd->newowner);
+ break;
+ case AT_ClusterOn: /* CLUSTER ON */
+ appendStringInfoString(str, "CLUSTER ON ");
+ break;
+ case AT_DropCluster: /* SET WITHOUT CLUSTER */
+ appendStringInfoString(str, "SET WITHOUT CLUSTER ");
+ break;
+ case AT_SetLogged: /* SET LOGGED */
+ appendStringInfoString(str, "SET LOGGED ");
+ break;
+ case AT_SetUnLogged: /* SET UNLOGGED */
+ appendStringInfoString(str, "SET UNLOGGED ");
+ break;
+ case AT_DropOids: /* SET WITHOUT OIDS */
+ appendStringInfoString(str, "SET WITHOUT OIDS ");
+ break;
+ case AT_SetTableSpace: /* SET TABLESPACE */
+ appendStringInfoString(str, "SET TABLESPACE ");
+ break;
+ case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
+ appendStringInfoString(str, "SET ");
+ break;
+ case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
+ appendStringInfoString(str, "RESET ");
+ break;
+ case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_EnableTrig: /* ENABLE TRIGGER name */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
+ appendStringInfoString(str, "ENABLE ALWAYS TRIGGER ");
+ break;
+ case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
+ appendStringInfoString(str, "ENABLE REPLICA TRIGGER ");
+ break;
+ case AT_DisableTrig: /* DISABLE TRIGGER name */
+ appendStringInfoString(str, "DISABLE TRIGGER ");
+ break;
+ case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
+ appendStringInfoString(str, "DISABLE TRIGGER ALL ");
+ break;
+ case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
+ appendStringInfoString(str, "ENABLE TRIGGER USER ");
+ break;
+ case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
+ appendStringInfoString(str, "DISABLE TRIGGER USER ");
+ break;
+ case AT_EnableRule: /* ENABLE RULE name */
+ appendStringInfoString(str, "ENABLE RULE ");
+ break;
+ case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
+ appendStringInfoString(str, "ENABLE ALWAYS RULE ");
+ break;
+ case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
+ appendStringInfoString(str, "ENABLE REPLICA RULE ");
+ break;
+ case AT_DisableRule: /* DISABLE RULE name */
+ appendStringInfoString(str, "DISABLE RULE ");
+ break;
+ case AT_AddInherit: /* INHERIT parent */
+ appendStringInfoString(str, "INHERIT ");
+ break;
+ case AT_DropInherit: /* NO INHERIT parent */
+ appendStringInfoString(str, "NO INHERIT ");
+ break;
+ case AT_AddOf: /* OF */
+ appendStringInfoString(str, "OF ");
+ break;
+ case AT_DropOf: /* NOT OF */
+ appendStringInfoString(str, "NOT OF ");
+ break;
+ case AT_ReplicaIdentity: /* REPLICA IDENTITY */
+ appendStringInfoString(str, "REPLICA IDENTITY ");
+ break;
+ case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
+ appendStringInfoString(str, "ENABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
+ appendStringInfoString(str, "DISABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
+ appendStringInfoString(str, "FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
+ appendStringInfoString(str, "NO FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_GenericOptions: /* OPTIONS (...) */
+ // Handled in def field handling
+ break;
+ case AT_AttachPartition: /* ATTACH PARTITION */
+ appendStringInfoString(str, "ATTACH PARTITION ");
+ break;
+ case AT_DetachPartition: /* DETACH PARTITION */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_DetachPartitionFinalize: /* DETACH PARTITION FINALIZE */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_AddIdentity: /* ADD IDENTITY */
+ appendStringInfoString(str, "ALTER ");
+ options = "ADD";
+ // Other details are output via the constraint node (in def field)
+ break;
+ case AT_SetIdentity: /* SET identity column options */
+ appendStringInfoString(str, "ALTER ");
+ break;
+ case AT_DropIdentity: /* DROP IDENTITY */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP IDENTITY";
+ trailing_missing_ok = true;
+ break;
+ }
+
+ if (alter_table_cmd->missing_ok && !trailing_missing_ok)
+ {
+ if (alter_table_cmd->subtype == AT_AddColumn)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ else
+ appendStringInfoString(str, "IF EXISTS ");
+ }
+
+ if (alter_table_cmd->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(alter_table_cmd->name));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->num > 0)
+ appendStringInfo(str, "%d ", alter_table_cmd->num);
+
+ if (options != NULL)
+ {
+ appendStringInfoString(str, options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->missing_ok && trailing_missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_DetachPartitionFinalize:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoString(str, "FINALIZE ");
+ break;
+ case AT_AddColumn:
+ case AT_AlterColumnType:
+ deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ColumnDefault:
+ if (alter_table_cmd->def != NULL)
+ {
+ deparseExpr(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case AT_SetStatistics:
+ deparseSignedIconst(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetOptions:
+ case AT_ResetOptions:
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+ deparseRelOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetStorage:
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetCompression:
+ if (strcmp(strVal(alter_table_cmd->def), "default") == 0)
+ appendStringInfoString(str, "DEFAULT");
+ else
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddIdentity:
+ case AT_AddConstraint:
+ case AT_AlterConstraint:
+ deparseConstraint(str, castNode(Constraint, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetIdentity:
+ deparseAlterIdentityColumnOptionList(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AlterColumnGenericOptions:
+ case AT_GenericOptions:
+ deparseAlterGenericOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddInherit:
+ case AT_DropInherit:
+ deparseRangeVar(str, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddOf:
+ deparseTypeName(str, castNode(TypeName, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ReplicaIdentity:
+ deparseReplicaIdentityStmt(str, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(alter_table_cmd->def == NULL);
+ break;
+ }
+
+ deparseOptDropBehavior(str, alter_table_cmd->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
+{
+ ListCell *lc;
+ DeparseNodeContext context = DEPARSE_NODE_CONTEXT_NONE;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_table_stmt->objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ context = DEPARSE_NODE_CONTEXT_ALTER_TYPE;
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (alter_table_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_table_stmt->relation, context);
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, alter_table_stmt->cmds)
+ {
+ deparseAlterTableCmd(str, castNode(AlterTableCmd, lfirst(lc)), context);
+ if (lnext(alter_table_stmt->cmds, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterTableSpaceOptionsStmt(StringInfo str, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
+{
+ appendStringInfoString(str, "ALTER TABLESPACE ");
+ deparseColId(str, alter_table_space_options_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_table_space_options_stmt->isReset)
+ appendStringInfoString(str, "RESET ");
+ else
+ appendStringInfoString(str, "SET ");
+
+ deparseRelOptions(str, alter_table_space_options_stmt->options);
+}
+
+static void deparseAlterDomainStmt(StringInfo str, AlterDomainStmt *alter_domain_stmt)
+{
+ appendStringInfoString(str, "ALTER DOMAIN ");
+ deparseAnyName(str, alter_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_domain_stmt->subtype)
+ {
+ case 'T':
+ if (alter_domain_stmt->def != NULL)
+ {
+ appendStringInfoString(str, "SET DEFAULT ");
+ deparseExpr(str, alter_domain_stmt->def);
+ }
+ else
+ {
+ appendStringInfoString(str, "DROP DEFAULT");
+ }
+ break;
+ case 'N':
+ appendStringInfoString(str, "DROP NOT NULL");
+ break;
+ case 'O':
+ appendStringInfoString(str, "SET NOT NULL");
+ break;
+ case 'C':
+ appendStringInfoString(str, "ADD ");
+ deparseConstraint(str, castNode(Constraint, alter_domain_stmt->def));
+ break;
+ case 'X':
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ if (alter_domain_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ if (alter_domain_stmt->behavior == DROP_CASCADE)
+ appendStringInfoString(str, " CASCADE");
+ break;
+ case 'V':
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ break;
+ default:
+ // No other subtypes supported by the parser
+ Assert(false);
+ }
+}
+
+static void deparseRenameStmt(StringInfo str, RenameStmt *rename_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_COLUMN:
+ switch (rename_stmt->relationType)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ Assert(false);
+ }
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_ATTRIBUTE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (rename_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, rename_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseColId(str, strVal(rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLUMN:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME COLUMN ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(strVal(rename_stmt->object)));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_DOMAIN:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TYPE:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_ATTRIBUTE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
+ appendStringInfoString(str, " RENAME ATTRIBUTE ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->newname));
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDropBehavior(str, rename_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_stmt)
+{
+ ListCell *lc;
+ switch (transaction_stmt->kind)
+ {
+ case TRANS_STMT_BEGIN:
+ appendStringInfoString(str, "BEGIN ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_START:
+ appendStringInfoString(str, "START TRANSACTION ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_COMMIT:
+ appendStringInfoString(str, "COMMIT ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_ROLLBACK:
+ appendStringInfoString(str, "ROLLBACK ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_SAVEPOINT:
+ appendStringInfoString(str, "SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_RELEASE:
+ appendStringInfoString(str, "RELEASE ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_ROLLBACK_TO:
+ appendStringInfoString(str, "ROLLBACK ");
+ appendStringInfoString(str, "TO SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_PREPARE:
+ appendStringInfoString(str, "PREPARE TRANSACTION ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_COMMIT_PREPARED:
+ appendStringInfoString(str, "COMMIT PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_ROLLBACK_PREPARED:
+ appendStringInfoString(str, "ROLLBACK PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
+{
+ ListCell *lc;
+
+ switch (variable_set_stmt->kind)
+ {
+ case VAR_SET_VALUE: /* SET var = value */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO ");
+ deparseVarList(str, variable_set_stmt->args);
+ break;
+ case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO DEFAULT");
+ break;
+ case VAR_SET_CURRENT: /* SET var FROM CURRENT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " FROM CURRENT");
+ break;
+ case VAR_SET_MULTI: /* special case for SET TRANSACTION ... */
+ Assert(variable_set_stmt->name != NULL);
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
+ {
+ appendStringInfoString(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION SNAPSHOT ");
+ deparseStringLiteral(str, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case VAR_RESET: /* RESET var */
+ appendStringInfoString(str, "RESET ");
+ deparseVarName(str, variable_set_stmt->name);
+ break;
+ case VAR_RESET_ALL: /* RESET ALL */
+ appendStringInfoString(str, "RESET ALL");
+ break;
+ }
+}
+
+static void deparseDropdbStmt(StringInfo str, DropdbStmt *dropdb_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "DROP DATABASE ");
+ if (dropdb_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, quote_identifier(dropdb_stmt->dbname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(dropdb_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, dropdb_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "force") == 0)
+ appendStringInfoString(str, "FORCE");
+ else
+ Assert(false); // Currently there are other supported values
+
+ if (lnext(dropdb_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ if (vacuum_stmt->is_vacuumcmd)
+ appendStringInfoString(str, "VACUUM ");
+ else
+ appendStringInfoString(str, "ANALYZE ");
+
+ deparseUtilityOptionList(str, vacuum_stmt->options);
+
+ foreach(lc, vacuum_stmt->rels)
+ {
+ Assert(IsA(lfirst(lc), VacuumRelation));
+ VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
+
+ deparseRangeVar(str, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(rel->va_cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc2, rel->va_cols)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc2))));
+ if (lnext(rel->va_cols, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ if (lnext(vacuum_stmt->rels, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLoadStmt(StringInfo str, LoadStmt *load_stmt)
+{
+ appendStringInfoString(str, "LOAD ");
+ deparseStringLiteral(str, load_stmt->filename);
+}
+
+static void deparseLockStmt(StringInfo str, LockStmt *lock_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "LOCK TABLE ");
+
+ deparseRelationExprList(str, lock_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (lock_stmt->mode != AccessExclusiveLock)
+ {
+ appendStringInfoString(str, "IN ");
+ switch (lock_stmt->mode)
+ {
+ case AccessShareLock:
+ appendStringInfoString(str, "ACCESS SHARE ");
+ break;
+ case RowShareLock:
+ appendStringInfoString(str, "ROW SHARE ");
+ break;
+ case RowExclusiveLock:
+ appendStringInfoString(str, "ROW EXCLUSIVE ");
+ break;
+ case ShareUpdateExclusiveLock:
+ appendStringInfoString(str, "SHARE UPDATE EXCLUSIVE ");
+ break;
+ case ShareLock:
+ appendStringInfoString(str, "SHARE ");
+ break;
+ case ShareRowExclusiveLock:
+ appendStringInfoString(str, "SHARE ROW EXCLUSIVE ");
+ break;
+ case ExclusiveLock:
+ appendStringInfoString(str, "EXCLUSIVE ");
+ break;
+ case AccessExclusiveLock:
+ appendStringInfoString(str, "ACCESS EXCLUSIVE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+ appendStringInfoString(str, "MODE ");
+ }
+
+ if (lock_stmt->nowait)
+ appendStringInfoString(str, "NOWAIT ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraintsSetStmt(StringInfo str, ConstraintsSetStmt *constraints_set_stmt)
+{
+ appendStringInfoString(str, "SET CONSTRAINTS ");
+
+ if (list_length(constraints_set_stmt->constraints) > 0)
+ {
+ deparseQualifiedNameList(str, constraints_set_stmt->constraints);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ if (constraints_set_stmt->deferred)
+ appendStringInfoString(str, "DEFERRED");
+ else
+ appendStringInfoString(str, "IMMEDIATE");
+}
+
+static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ appendStringInfoString(str, "EXPLAIN ");
+
+ deparseUtilityOptionList(str, explain_stmt->options);
+
+ deparseExplainableStmt(str, explain_stmt->query);
+}
+
+static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "COPY ");
+
+ if (copy_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(copy_stmt->attlist) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, copy_stmt->attlist);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (copy_stmt->query != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, copy_stmt->query);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "FROM ");
+ else
+ appendStringInfoString(str, "TO ");
+
+ if (copy_stmt->is_program)
+ appendStringInfoString(str, "PROGRAM ");
+
+ if (copy_stmt->filename != NULL)
+ {
+ deparseStringLiteral(str, copy_stmt->filename);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "STDIN ");
+ else
+ appendStringInfoString(str, "STDOUT ");
+ }
+
+ if (list_length(copy_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "WITH (");
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "format") == 0)
+ {
+ appendStringInfoString(str, "FORMAT ");
+
+ char *format = strVal(def_elem->arg);
+ if (strcmp(format, "binary") == 0)
+ appendStringInfoString(str, "BINARY");
+ else if (strcmp(format, "csv") == 0)
+ appendStringInfoString(str, "CSV");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "freeze") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
+ {
+ appendStringInfoString(str, "FREEZE");
+ if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
+ appendStringInfoString(str, " 1");
+ }
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
+ {
+ appendStringInfoString(str, "DELIMITER ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "null") == 0)
+ {
+ appendStringInfoString(str, "NULL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "header") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
+ {
+ appendStringInfoString(str, "HEADER");
+ if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
+ appendStringInfoString(str, " 1");
+ }
+ else if (strcmp(def_elem->defname, "quote") == 0)
+ {
+ appendStringInfoString(str, "QUOTE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "escape") == 0)
+ {
+ appendStringInfoString(str, "ESCAPE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
+ {
+ appendStringInfoString(str, "FORCE_QUOTE ");
+ if (IsA(def_elem->arg, A_Star))
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NOT_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "force_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "encoding") == 0)
+ {
+ appendStringInfoString(str, "ENCODING ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL)
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ {
+ // Nothing
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ {
+ deparseNumericOnly(str, (Value *) def_elem->arg);
+ }
+ else if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAStar(str, castNode(A_Star, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoChar(str, '(');
+ foreach(lc2, l)
+ {
+ deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ }
+
+ if (lnext(copy_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseWhereClause(str, copy_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDoStmt(StringInfo str, DoStmt *do_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DO ");
+
+ foreach (lc, do_stmt->args)
+ {
+ DefElem *defel = castNode(DefElem, lfirst(lc));
+ if (strcmp(defel->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(defel->arg)));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defel->defname, "as") == 0)
+ {
+ char *strval = strVal(defel->arg);
+ const char *delim = "$$";
+ if (strstr(strval, "$$") != NULL)
+ delim = "$outer$";
+ appendStringInfoString(str, delim);
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, delim);
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDiscardStmt(StringInfo str, DiscardStmt *discard_stmt)
+{
+ appendStringInfoString(str, "DISCARD ");
+ switch (discard_stmt->target)
+ {
+ case DISCARD_ALL:
+ appendStringInfoString(str, "ALL");
+ break;
+ case DISCARD_PLANS:
+ appendStringInfoString(str, "PLANS");
+ break;
+ case DISCARD_SEQUENCES:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case DISCARD_TEMP:
+ appendStringInfoString(str, "TEMP");
+ break;
+ }
+}
+
+static void deparseDefineStmt(StringInfo str, DefineStmt *define_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (define_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ default:
+ // This shouldn't happen
+ Assert(false);
+ break;
+ }
+
+ if (define_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseFuncName(str, define_stmt->defnames);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAnyOperator(str, define_stmt->defnames);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_COLLATION:
+ deparseAnyName(str, define_stmt->defnames);
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
+ {
+ deparseAggrArgs(str, define_stmt->args);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (define_stmt->kind == OBJECT_COLLATION &&
+ list_length(define_stmt->definition) == 1 &&
+ strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
+ }
+ else if (list_length(define_stmt->definition) > 0)
+ {
+ deparseDefinition(str, define_stmt->definition);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCompositeTypeStmt(StringInfo str, CompositeTypeStmt *composite_type_stmt)
+{
+ ListCell *lc;
+ RangeVar *typevar;
+
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseRangeVar(str, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
+
+ appendStringInfoString(str, " AS (");
+ foreach(lc, composite_type_stmt->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(composite_type_stmt->coldeflist, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateEnumStmt(StringInfo str, CreateEnumStmt *create_enum_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE TYPE ");
+
+ deparseAnyName(str, create_enum_stmt->typeName);
+ appendStringInfoString(str, " AS ENUM (");
+ foreach(lc, create_enum_stmt->vals)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(create_enum_stmt->vals, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateRangeStmt(StringInfo str, CreateRangeStmt *create_range_stmt)
+{
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseAnyName(str, create_range_stmt->typeName);
+ appendStringInfoString(str, " AS RANGE ");
+ deparseDefinition(str, create_range_stmt->params);
+}
+
+static void deparseAlterEnumStmt(StringInfo str, AlterEnumStmt *alter_enum_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_enum_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->oldVal == NULL)
+ {
+ appendStringInfoString(str, "ADD VALUE ");
+ if (alter_enum_stmt->skipIfNewValExists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->newValNeighbor)
+ {
+ if (alter_enum_stmt->newValIsAfter)
+ appendStringInfoString(str, "AFTER ");
+ else
+ appendStringInfoString(str, "BEFORE ");
+ deparseStringLiteral(str, alter_enum_stmt->newValNeighbor);
+ }
+ }
+ else
+ {
+ appendStringInfoString(str, "RENAME VALUE ");
+ deparseStringLiteral(str, alter_enum_stmt->oldVal);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionStmt(StringInfo str, AlterExtensionStmt *alter_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_stmt->extname);
+ appendStringInfoString(str, " UPDATE ");
+ foreach (lc, alter_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionContentsStmt(StringInfo str, AlterExtensionContentsStmt *alter_extension_contents_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_contents_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_extension_contents_stmt->action == 1)
+ appendStringInfoString(str, "ADD ");
+ else if (alter_extension_contents_stmt->action == -1)
+ appendStringInfoString(str, "DROP ");
+ else
+ Assert(false);
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ // No other object types are supported here in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ // any_name
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_TABLE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ deparseAnyName(str, castNode(List, alter_extension_contents_stmt->object));
+ break;
+ // name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_LANGUAGE:
+ case OBJECT_SCHEMA:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ deparseColId(str, strVal(alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ deparseTypeName(str, castNode(TypeName, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
+{
+ ListCell *lc;
+
+ if (access_priv->priv_name != NULL)
+ {
+ if (strcmp(access_priv->priv_name, "select") == 0)
+ appendStringInfoString(str, "select");
+ else if (strcmp(access_priv->priv_name, "references") == 0)
+ appendStringInfoString(str, "references");
+ else if (strcmp(access_priv->priv_name, "create") == 0)
+ appendStringInfoString(str, "create");
+ else
+ appendStringInfoString(str, quote_identifier(access_priv->priv_name));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(access_priv->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, access_priv->cols);
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
+{
+ ListCell *lc;
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "GRANT OPTION FOR ");
+
+ if (list_length(grant_stmt->privileges) > 0)
+ {
+ foreach(lc, grant_stmt->privileges)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_stmt->privileges, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ deparsePrivilegeTarget(str, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ foreach(lc, grant_stmt->grantees)
+ {
+ deparseRoleSpec(str, castNode(RoleSpec, lfirst(lc)));
+ if (lnext(grant_stmt->grantees, lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "WITH GRANT OPTION ");
+
+ deparseOptDropBehavior(str, grant_stmt->behavior);
+
+ if (grant_stmt->grantor)
+ {
+ appendStringInfoString(str, "GRANTED BY ");
+ deparseRoleSpec(str, castNode(RoleSpec, grant_stmt->grantor));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
+{
+ ListCell *lc;
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_role_stmt->is_grant && grant_role_stmt->admin_opt)
+ appendStringInfoString(str, "ADMIN OPTION FOR ");
+
+ foreach(lc, grant_role_stmt->granted_roles)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_role_stmt->granted_roles, lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ deparseRoleList(str, grant_role_stmt->grantee_roles);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_role_stmt->is_grant && grant_role_stmt->admin_opt)
+ appendStringInfoString(str, "WITH ADMIN OPTION ");
+
+ if (grant_role_stmt->grantor)
+ {
+ appendStringInfoString(str, "GRANTED BY ");
+ deparseRoleSpec(str, castNode(RoleSpec, grant_role_stmt->grantor));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropRoleStmt(StringInfo str, DropRoleStmt *drop_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DROP ROLE ");
+
+ if (drop_role_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRoleList(str, drop_role_stmt->roles);
+}
+
+static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (index_stmt->unique)
+ appendStringInfoString(str, "UNIQUE ");
+
+ appendStringInfoString(str, "INDEX ");
+
+ if (index_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (index_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (index_stmt->idxname != NULL)
+ {
+ appendStringInfoString(str, index_stmt->idxname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (index_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(index_stmt->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, index_stmt->indexParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+
+ if (list_length(index_stmt->indexIncludingParams) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ foreach (lc, index_stmt->indexIncludingParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexIncludingParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, index_stmt->options);
+
+ if (index_stmt->tableSpace != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(index_stmt->tableSpace));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, index_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterOpFamilyStmt(StringInfo str, AlterOpFamilyStmt *alter_op_family_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR FAMILY ");
+ deparseAnyName(str, alter_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(alter_op_family_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_op_family_stmt->isDrop)
+ appendStringInfoString(str, "DROP ");
+ else
+ appendStringInfoString(str, "ADD ");
+
+ deparseOpclassItemList(str, alter_op_family_stmt->items);
+}
+
+static void deparsePrepareStmt(StringInfo str, PrepareStmt *prepare_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "PREPARE ");
+ deparseColId(str, prepare_stmt->name);
+ if (list_length(prepare_stmt->argtypes) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, prepare_stmt->argtypes);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoString(str, " AS ");
+ deparsePreparableStmt(str, prepare_stmt->query);
+}
+
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "EXECUTE ");
+ appendStringInfoString(str, quote_identifier(execute_stmt->name));
+ if (list_length(execute_stmt->params) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, execute_stmt->params);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseDeallocateStmt(StringInfo str, DeallocateStmt *deallocate_stmt)
+{
+ appendStringInfoString(str, "DEALLOCATE ");
+ if (deallocate_stmt->name != NULL)
+ appendStringInfoString(str, quote_identifier(deallocate_stmt->name));
+ else
+ appendStringInfoString(str, "ALL");
+}
+
+// "AlterOptRoleElem" in gram.y
+static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "password") == 0)
+ {
+ appendStringInfoString(str, "PASSWORD ");
+ if (def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NULL");
+ }
+ else if (IsA(def_elem->arg, ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "connectionlimit") == 0)
+ {
+ appendStringInfo(str, "CONNECTION LIMIT %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validUntil") == 0)
+ {
+ appendStringInfoString(str, "VALID UNTIL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "SUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOSUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOCREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "REPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOREPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "CREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOCREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "LOGIN");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOLOGIN");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "BYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOBYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 1)
+ {
+ appendStringInfoString(str, "INHERIT");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 0)
+ {
+ appendStringInfoString(str, "NOINHERIT");
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "CreateOptRoleElem" in gram.y
+static void deparseCreateRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "sysid") == 0)
+ {
+ appendStringInfo(str, "SYSID %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "adminmembers") == 0)
+ {
+ appendStringInfoString(str, "ADMIN ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "addroleto") == 0)
+ {
+ appendStringInfoString(str, "IN ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ deparseAlterRoleElem(str, def_elem);
+ }
+}
+
+static void deparseCreatePLangStmt(StringInfo str, CreatePLangStmt *create_p_lang_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+
+ if (create_p_lang_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ if (create_p_lang_stmt->pltrusted)
+ appendStringInfoString(str, "TRUSTED ");
+
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, create_p_lang_stmt->plname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_p_lang_stmt->plhandler);
+ appendStringInfoChar(str, ' ');
+
+ if (create_p_lang_stmt->plinline)
+ {
+ appendStringInfoString(str, "INLINE ");
+ deparseHandlerName(str, create_p_lang_stmt->plinline);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_p_lang_stmt->plvalidator)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, create_p_lang_stmt->plvalidator);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateRoleStmt(StringInfo str, CreateRoleStmt *create_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ switch (create_role_stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case ROLESTMT_USER:
+ appendStringInfoString(str, "USER ");
+ break;
+ case ROLESTMT_GROUP:
+ appendStringInfoString(str, "GROUP ");
+ break;
+ }
+
+ appendStringInfoString(str, quote_identifier(create_role_stmt->role));
+ appendStringInfoChar(str, ' ');
+
+ if (create_role_stmt->options != NULL)
+ {
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, create_role_stmt->options)
+ {
+ deparseCreateRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleStmt(StringInfo str, AlterRoleStmt *alter_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "GROUP ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_stmt->action == 1)
+ {
+ appendStringInfoString(str, "ADD USER ");
+ }
+ else if (alter_role_stmt->action == -1)
+ {
+ appendStringInfoString(str, "DROP USER ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseRoleList(str, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, alter_role_stmt->options)
+ {
+ deparseAlterRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeclareCursorStmt(StringInfo str, DeclareCursorStmt *declare_cursor_stmt)
+{
+ appendStringInfoString(str, "DECLARE ");
+ appendStringInfoString(str, quote_identifier(declare_cursor_stmt->portalname));
+ appendStringInfoChar(str, ' ');
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
+ appendStringInfoString(str, "BINARY ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
+ appendStringInfoString(str, "SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
+ appendStringInfoString(str, "NO SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
+ appendStringInfoString(str, "INSENSITIVE ");
+
+ appendStringInfoString(str, "CURSOR ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
+ appendStringInfoString(str, "WITH HOLD ");
+
+ appendStringInfoString(str, "FOR ");
+
+ deparseSelectStmt(str, castNode(SelectStmt, declare_cursor_stmt->query));
+}
+
+static void deparseFetchStmt(StringInfo str, FetchStmt *fetch_stmt)
+{
+ if (fetch_stmt->ismove)
+ appendStringInfoString(str, "MOVE ");
+ else
+ appendStringInfoString(str, "FETCH ");
+
+ switch (fetch_stmt->direction)
+ {
+ case FETCH_FORWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ // Default
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "FORWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_BACKWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "PRIOR ");
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "BACKWARD ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "BACKWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_ABSOLUTE:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "FIRST ");
+ }
+ else if (fetch_stmt->howMany == -1)
+ {
+ appendStringInfoString(str, "LAST ");
+ }
+ else
+ {
+ appendStringInfo(str, "ABSOLUTE %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_RELATIVE:
+ appendStringInfo(str, "RELATIVE %ld ", fetch_stmt->howMany);
+ }
+
+ appendStringInfoString(str, fetch_stmt->portalname);
+}
+
+static void deparseAlterDefaultPrivilegesStmt(StringInfo str, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER DEFAULT PRIVILEGES ");
+
+ foreach (lc, alter_default_privileges_stmt->options)
+ {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp(defelem->defname, "schemas") == 0)
+ {
+ appendStringInfoString(str, "IN SCHEMA ");
+ deparseNameList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defelem->defname, "roles") == 0)
+ {
+ appendStringInfoString(str, "FOR ROLE ");
+ deparseRoleList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ // No other DefElems are supported
+ Assert(false);
+ }
+ }
+
+ deparseGrantStmt(str, alter_default_privileges_stmt->action);
+}
+
+static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
+{
+ appendStringInfoString(str, "REINDEX ");
+
+ deparseUtilityOptionList(str, reindex_stmt->params);
+
+ switch (reindex_stmt->kind)
+ {
+ case REINDEX_OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case REINDEX_OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case REINDEX_OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case REINDEX_OBJECT_SYSTEM:
+ appendStringInfoString(str, "SYSTEM ");
+ break;
+ case REINDEX_OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ }
+
+ if (reindex_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (reindex_stmt->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(reindex_stmt->name));
+ }
+}
+
+static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (rule_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "RULE ");
+ appendStringInfoString(str, quote_identifier(rule_stmt->rulename));
+ appendStringInfoString(str, " AS ON ");
+
+ switch (rule_stmt->event)
+ {
+ case CMD_UNKNOWN:
+ case CMD_UTILITY:
+ case CMD_NOTHING:
+ // Not supported here
+ Assert(false);
+ break;
+ case CMD_SELECT:
+ appendStringInfoString(str, "SELECT ");
+ break;
+ case CMD_UPDATE:
+ appendStringInfoString(str, "UPDATE ");
+ break;
+ case CMD_INSERT:
+ appendStringInfoString(str, "INSERT ");
+ break;
+ case CMD_DELETE:
+ appendStringInfoString(str, "DELETE ");
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ deparseRangeVar(str, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseWhereClause(str, rule_stmt->whereClause);
+
+ appendStringInfoString(str, "DO ");
+
+ if (rule_stmt->instead)
+ appendStringInfoString(str, "INSTEAD ");
+
+ if (list_length(rule_stmt->actions) == 0)
+ {
+ appendStringInfoString(str, "NOTHING");
+ }
+ else if (list_length(rule_stmt->actions) == 1)
+ {
+ deparseRuleActionStmt(str, linitial(rule_stmt->actions));
+ }
+ else
+ {
+ appendStringInfoChar(str, '(');
+ foreach (lc, rule_stmt->actions)
+ {
+ deparseRuleActionStmt(str, lfirst(lc));
+ if (lnext(rule_stmt->actions, lc))
+ appendStringInfoString(str, "; ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseNotifyStmt(StringInfo str, NotifyStmt *notify_stmt)
+{
+ appendStringInfoString(str, "NOTIFY ");
+ appendStringInfoString(str, quote_identifier(notify_stmt->conditionname));
+
+ if (notify_stmt->payload != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseStringLiteral(str, notify_stmt->payload);
+ }
+}
+
+static void deparseListenStmt(StringInfo str, ListenStmt *listen_stmt)
+{
+ appendStringInfoString(str, "LISTEN ");
+ appendStringInfoString(str, quote_identifier(listen_stmt->conditionname));
+}
+
+static void deparseUnlistenStmt(StringInfo str, UnlistenStmt *unlisten_stmt)
+{
+ appendStringInfoString(str, "UNLISTEN ");
+ if (unlisten_stmt->conditionname == NULL)
+ appendStringInfoString(str, "*");
+ else
+ appendStringInfoString(str, quote_identifier(unlisten_stmt->conditionname));
+}
+
+static void deparseCreateSeqStmt(StringInfo str, CreateSeqStmt *create_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_seq_stmt->sequence->relpersistence);
+
+ appendStringInfoString(str, "SEQUENCE ");
+
+ if (create_seq_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptSeqOptList(str, create_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFunctionStmt(StringInfo str, AlterFunctionStmt *alter_function_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_function_stmt->objtype)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ deparseFunctionWithArgtypes(str, alter_function_stmt->func);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, alter_function_stmt->actions)
+ {
+ deparseCommonFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ if (lnext(alter_function_stmt->actions, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseTruncateStmt(StringInfo str, TruncateStmt *truncate_stmt)
+{
+ appendStringInfoString(str, "TRUNCATE ");
+
+ deparseRelationExprList(str, truncate_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (truncate_stmt->restart_seqs)
+ appendStringInfoString(str, "RESTART IDENTITY ");
+
+ deparseOptDropBehavior(str, truncate_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateEventTrigStmt(StringInfo str, CreateEventTrigStmt *create_event_trig_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "CREATE EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "ON ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->eventname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_event_trig_stmt->whenclause)
+ {
+ appendStringInfoString(str, "WHEN ");
+
+ foreach (lc, create_event_trig_stmt->whenclause)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " IN (");
+ foreach (lc2, l)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ if (lnext(create_event_trig_stmt->whenclause, lc))
+ appendStringInfoString(str, " AND ");
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_event_trig_stmt->funcname);
+ appendStringInfoString(str, "()");
+}
+
+static void deparseAlterEventTrigStmt(StringInfo str, AlterEventTrigStmt *alter_event_trig_stmt)
+{
+ appendStringInfoString(str, "ALTER EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(alter_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_event_trig_stmt->tgenabled)
+ {
+ case TRIGGER_FIRES_ON_ORIGIN:
+ appendStringInfoString(str, "ENABLE");
+ break;
+ case TRIGGER_FIRES_ON_REPLICA:
+ appendStringInfoString(str, "ENABLE REPLICA");
+ break;
+ case TRIGGER_FIRES_ALWAYS:
+ appendStringInfoString(str, "ENABLE ALWAYS");
+ break;
+ case TRIGGER_DISABLED:
+ appendStringInfoString(str, "DISABLE");
+ break;
+ }
+}
+
+static void deparseRefreshMatViewStmt(StringInfo str, RefreshMatViewStmt *refresh_mat_view_stmt)
+{
+ appendStringInfoString(str, "REFRESH MATERIALIZED VIEW ");
+
+ if (refresh_mat_view_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ deparseRangeVar(str, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (refresh_mat_view_stmt->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt)
+{
+ switch (replica_identity_stmt->identity_type)
+ {
+ case REPLICA_IDENTITY_NOTHING:
+ appendStringInfoString(str, "NOTHING ");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ appendStringInfoString(str, "FULL ");
+ break;
+ case REPLICA_IDENTITY_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ Assert(replica_identity_stmt->name != NULL);
+ appendStringInfoString(str, "USING INDEX ");
+ appendStringInfoString(str, quote_identifier(replica_identity_stmt->name));
+ break;
+ }
+}
+
+static void deparseCreatePolicyStmt(StringInfo str, CreatePolicyStmt *create_policy_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE POLICY ");
+ deparseColId(str, create_policy_stmt->policy_name);
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (!create_policy_stmt->permissive)
+ appendStringInfoString(str, "AS RESTRICTIVE ");
+
+ if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
+ Assert(true); // Default
+ else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
+ appendStringInfoString(str, "FOR SELECT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
+ appendStringInfoString(str, "FOR INSERT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
+ appendStringInfoString(str, "FOR UPDATE ");
+ else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
+ appendStringInfoString(str, "FOR DELETE ");
+ else
+ Assert(false);
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, create_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ if (create_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, create_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (create_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, create_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseAlterPolicyStmt(StringInfo str, AlterPolicyStmt *alter_policy_stmt)
+{
+ appendStringInfoString(str, "ALTER POLICY ");
+ appendStringInfoString(str, quote_identifier(alter_policy_stmt->policy_name));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_policy_stmt->roles) > 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, alter_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, alter_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (alter_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, alter_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *create_table_space_stmt)
+{
+ appendStringInfoString(str, "CREATE TABLESPACE ");
+ deparseColId(str, create_table_space_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_space_stmt->owner != NULL)
+ {
+ appendStringInfoString(str, "OWNER ");
+ deparseRoleSpec(str, create_table_space_stmt->owner);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "LOCATION ");
+ deparseStringLiteral(str, create_table_space_stmt->location);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptWith(str, create_table_space_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTransformStmt(StringInfo str, CreateTransformStmt *create_transform_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_transform_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "TRANSFORM FOR ");
+ deparseTypeName(str, create_transform_stmt->type_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(create_transform_stmt->lang));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoChar(str, '(');
+
+ if (create_transform_stmt->fromsql)
+ {
+ appendStringInfoString(str, "FROM SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->fromsql);
+ }
+
+ if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
+ appendStringInfoString(str, ", ");
+
+ if (create_transform_stmt->tosql)
+ {
+ appendStringInfoString(str, "TO SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->tosql);
+ }
+
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
+{
+ appendStringInfoString(str, "CREATE ACCESS METHOD ");
+ appendStringInfoString(str, quote_identifier(create_am_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TYPE ");
+ switch (create_am_stmt->amtype)
+ {
+ case AMTYPE_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case AMTYPE_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ }
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_am_stmt->handler_name);
+}
+
+static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_publication_stmt->tables) > 0)
+ {
+ appendStringInfoString(str, "FOR TABLE ");
+ deparseRelationExprList(str, create_publication_stmt->tables);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_publication_stmt->for_all_tables)
+ {
+ appendStringInfoString(str, "FOR ALL TABLES ");
+ }
+
+ deparseOptDefinition(str, create_publication_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *alter_publication_stmt)
+{
+ appendStringInfoString(str, "ALTER PUBLICATION ");
+ deparseColId(str, alter_publication_stmt->pubname);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_publication_stmt->tables) > 0)
+ {
+ switch (alter_publication_stmt->tableAction)
+ {
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET TABLE ");
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD TABLE ");
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP TABLE ");
+ break;
+ case DEFELEM_UNSPEC:
+ Assert(false);
+ break;
+ }
+
+ deparseRelationExprList(str, alter_publication_stmt->tables);
+ }
+ else if (list_length(alter_publication_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_publication_stmt->options);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+static void deparseAlterSeqStmt(StringInfo str, AlterSeqStmt *alter_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SEQUENCE ");
+
+ if (alter_seq_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseSeqOptList(str, alter_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSystemStmt(StringInfo str, AlterSystemStmt *alter_system_stmt)
+{
+ appendStringInfoString(str, "ALTER SYSTEM ");
+ deparseVariableSetStmt(str, alter_system_stmt->setstmt);
+}
+
+static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "COMMENT ON ");
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ deparseAnyName(str, castNode(List, comment_stmt->object));
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(strVal(comment_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ deparseTypeName(str, castNode(TypeName, comment_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON DOMAIN ");
+ deparseTypeName(str, linitial(l));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(lsecond(l))));
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, comment_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseValue(str, (Value *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (comment_stmt->comment != NULL)
+ deparseStringLiteral(str, comment_stmt->comment);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseStatsElem(StringInfo str, StatsElem *stats_elem)
+{
+ // only one of stats_elem->name or stats_elem->expr can be non-null
+ if (stats_elem->name)
+ appendStringInfoString(str, stats_elem->name);
+ else if (stats_elem->expr)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, stats_elem->expr);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE STATISTICS ");
+
+ if (create_stats_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseAnyName(str, create_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_stats_stmt->stat_types) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, create_stats_stmt->stat_types);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ foreach (lc, create_stats_stmt->exprs)
+ {
+ deparseStatsElem(str, lfirst(lc));
+ if (lnext(create_stats_stmt->exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, " FROM ");
+ deparseFromList(str, create_stats_stmt->relations);
+}
+
+static void deparseAlterCollationStmt(StringInfo str, AlterCollationStmt *alter_collation_stmt)
+{
+ appendStringInfoString(str, "ALTER COLLATION ");
+ deparseAnyName(str, alter_collation_stmt->collname);
+ appendStringInfoString(str, " REFRESH VERSION");
+}
+
+static void deparseAlterDatabaseStmt(StringInfo str, AlterDatabaseStmt *alter_database_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, alter_database_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterDatabaseSetStmt(StringInfo str, AlterDatabaseSetStmt *alter_database_set_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_set_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseVariableSetStmt(str, alter_database_set_stmt->setstmt);
+}
+
+static void deparseAlterStatsStmt(StringInfo str, AlterStatsStmt *alter_stats_stmt)
+{
+ appendStringInfoString(str, "ALTER STATISTICS ");
+
+ if (alter_stats_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseAnyName(str, alter_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfo(str, "SET STATISTICS %d", alter_stats_stmt->stxstattarget);
+}
+
+static void deparseAlterTSDictionaryStmt(StringInfo str, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
+{
+ appendStringInfoString(str, "ALTER TEXT SEARCH DICTIONARY ");
+
+ deparseAnyName(str, alter_ts_dictionary_stmt->dictname);
+ appendStringInfoChar(str, ' ');
+
+ deparseDefinition(str, alter_ts_dictionary_stmt->options);
+}
+
+static void deparseAlterTSConfigurationStmt(StringInfo str, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, alter_ts_configuration_stmt->cfgname);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_ts_configuration_stmt->kind)
+ {
+ case ALTER_TSCONFIG_ADD_MAPPING:
+ appendStringInfoString(str, "ADD MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT:
+ appendStringInfoString(str, "ALTER MAPPING REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_DROP_MAPPING:
+ appendStringInfoString(str, "DROP MAPPING ");
+ if (alter_ts_configuration_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, "FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ break;
+ }
+}
+
+static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_show_stmt)
+{
+ appendStringInfoString(str, "SHOW ");
+
+ if (strcmp(variable_show_stmt->name, "timezone") == 0)
+ appendStringInfoString(str, "TIME ZONE");
+ else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
+ appendStringInfoString(str, "TRANSACTION ISOLATION LEVEL");
+ else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
+ appendStringInfoString(str, "SESSION AUTHORIZATION");
+ else if (strcmp(variable_show_stmt->name, "all") == 0)
+ appendStringInfoString(str, "SESSION ALL");
+ else
+ appendStringInfoString(str, quote_identifier(variable_show_stmt->name));
+}
+
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
+{
+ deparseRangeVar(str, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
+
+ appendStringInfoString(str, " TABLESAMPLE ");
+
+ deparseFuncName(str, range_table_sample->method);
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, range_table_sample->args);
+ appendStringInfoString(str, ") ");
+
+ if (range_table_sample->repeatable != NULL)
+ {
+ appendStringInfoString(str, "REPEATABLE (");
+ deparseExpr(str, range_table_sample->repeatable);
+ appendStringInfoString(str, ") ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateSubscriptionStmt(StringInfo str, CreateSubscriptionStmt *create_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(create_subscription_stmt->subname));
+
+ appendStringInfoString(str, " CONNECTION ");
+ if (create_subscription_stmt->conninfo != NULL)
+ deparseStringLiteral(str, create_subscription_stmt->conninfo);
+ else
+ appendStringInfoString(str, "''");
+
+ appendStringInfoString(str, " PUBLICATION ");
+
+ foreach(lc, create_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(create_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDefinition(str, create_subscription_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *alter_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(alter_subscription_stmt->subname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_subscription_stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ appendStringInfoString(str, "CONNECTION ");
+ deparseStringLiteral(str, alter_subscription_stmt->conninfo);
+ appendStringInfoChar(str, ' ');
+ break;
+ case ALTER_SUBSCRIPTION_REFRESH:
+ appendStringInfoString(str, "REFRESH PUBLICATION ");
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ADD_PUBLICATION:
+ appendStringInfoString(str, "ADD PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_DROP_PUBLICATION:
+ appendStringInfoString(str, "DROP PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SET_PUBLICATION:
+ appendStringInfoString(str, "SET PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ENABLED:
+ Assert(list_length(alter_subscription_stmt->options) == 1);
+ DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
+ Assert(strcmp(defelem->defname, "enabled") == 0);
+ if (intVal(defelem->arg) == 1)
+ {
+ appendStringInfoString(str, " ENABLE ");
+ }
+ else if (intVal(defelem->arg) == 0)
+ {
+ appendStringInfoString(str, " DISABLE ");
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropSubscriptionStmt(StringInfo str, DropSubscriptionStmt *drop_subscription_stmt)
+{
+ appendStringInfoString(str, "DROP SUBSCRIPTION ");
+
+ if (drop_subscription_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_subscription_stmt->subname);
+}
+
+static void deparseCallStmt(StringInfo str, CallStmt *call_stmt)
+{
+ appendStringInfoString(str, "CALL ");
+ deparseFuncCall(str, call_stmt->funccall);
+}
+
+static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_owner_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnly(str, (Value *) alter_owner_stmt->object);
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ default:
+ Assert(false);
+ }
+
+ appendStringInfoString(str, " OWNER TO ");
+ deparseRoleSpec(str, alter_owner_stmt->newowner);
+}
+
+// "operator_def_list" in gram.y
+static void deparseOperatorDefList(StringInfo str, List *defs)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, defs)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " = ");
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, true);
+ else
+ appendStringInfoString(str, "NONE");
+
+ if (lnext(defs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterOperatorStmt(StringInfo str, AlterOperatorStmt *alter_operator_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR ");
+ deparseOperatorWithArgtypes(str, alter_operator_stmt->opername);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_operator_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseAlterTypeStmt(StringInfo str, AlterTypeStmt *alter_type_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_type_stmt->typeName);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_type_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseDropOwnedStmt(StringInfo str, DropOwnedStmt *drop_owned_stmt)
+{
+ appendStringInfoString(str, "DROP OWNED BY ");
+ deparseRoleList(str, drop_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ deparseOptDropBehavior(str, drop_owned_stmt->behavior);
+ removeTrailingSpace(str);
+}
+
+static void deparseReassignOwnedStmt(StringInfo str, ReassignOwnedStmt *reassigned_owned_stmt)
+{
+ appendStringInfoString(str, "REASSIGN OWNED BY ");
+
+ deparseRoleList(str, reassigned_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleSpec(str, reassigned_owned_stmt->newrole);
+}
+
+static void deparseClosePortalStmt(StringInfo str, ClosePortalStmt *close_portal_stmt)
+{
+ appendStringInfoString(str, "CLOSE ");
+ if (close_portal_stmt->portalname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(close_portal_stmt->portalname));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+}
+
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr)
+{
+ appendStringInfoString(str, "CURRENT OF ");
+ appendStringInfoString(str, quote_identifier(current_of_expr->cursor_name));
+}
+
+static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_stmt)
+{
+ ListCell *lc;
+ bool skip_events_or = true;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_trig_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_trig_stmt->isconstraint)
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, "TRIGGER ");
+
+ appendStringInfoString(str, quote_identifier(create_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (create_trig_stmt->timing)
+ {
+ case TRIGGER_TYPE_BEFORE:
+ appendStringInfoString(str, "BEFORE ");
+ break;
+ case TRIGGER_TYPE_AFTER:
+ appendStringInfoString(str, "AFTER ");
+ break;
+ case TRIGGER_TYPE_INSTEAD:
+ appendStringInfoString(str, "INSTEAD OF ");
+ break;
+ default:
+ Assert(false);
+ }
+
+ if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
+ {
+ appendStringInfoString(str, "INSERT ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "DELETE ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "UPDATE ");
+ if (list_length(create_trig_stmt->columns) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseColumnList(str, create_trig_stmt->columns);
+ appendStringInfoChar(str, ' ');
+ }
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "TRUNCATE ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_trig_stmt->transitionRels != NULL)
+ {
+ appendStringInfoString(str, "REFERENCING ");
+ foreach(lc, create_trig_stmt->transitionRels)
+ {
+ deparseTriggerTransition(str, castNode(TriggerTransition, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ if (create_trig_stmt->constrrel != NULL)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseRangeVar(str, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_trig_stmt->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (create_trig_stmt->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (create_trig_stmt->row)
+ appendStringInfoString(str, "FOR EACH ROW ");
+
+ if (create_trig_stmt->whenClause)
+ {
+ appendStringInfoString(str, "WHEN (");
+ deparseExpr(str, create_trig_stmt->whenClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_trig_stmt->funcname);
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_trig_stmt->args)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(create_trig_stmt->args, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition)
+{
+ if (trigger_transition->isNew)
+ appendStringInfoString(str, "NEW ");
+ else
+ appendStringInfoString(str, "OLD ");
+
+ if (trigger_transition->isTable)
+ appendStringInfoString(str, "TABLE ");
+ else
+ appendStringInfoString(str, "ROW ");
+
+ appendStringInfoString(str, quote_identifier(trigger_transition->name));
+}
+
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
+{
+ switch (xml_expr->op)
+ {
+ case IS_XMLCONCAT: /* XMLCONCAT(args) */
+ appendStringInfoString(str, "xmlconcat(");
+ deparseExprList(str, xml_expr->args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
+ appendStringInfoString(str, "xmlelement(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->named_args != NULL)
+ {
+ appendStringInfoString(str, ", xmlattributes(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoString(str, ")");
+ }
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExprList(str, xml_expr->args);
+ }
+ appendStringInfoString(str, ")");
+ break;
+ case IS_XMLFOREST: /* XMLFOREST(xml_attributes) */
+ appendStringInfoString(str, "xmlforest(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
+ Assert(list_length(xml_expr->args) == 2);
+ appendStringInfoString(str, "xmlparse(");
+ switch (xml_expr->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, linitial(xml_expr->args));
+ if (strcmp(strVal(&castNode(A_Const, castNode(TypeCast, lsecond(xml_expr->args))->arg)->val), "t") == 0)
+ appendStringInfoString(str, " PRESERVE WHITESPACE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPI: /* XMLPI(name [, args]) */
+ appendStringInfoString(str, "xmlpi(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, linitial(xml_expr->args));
+ }
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
+ appendStringInfoString(str, "xmlroot(");
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, ", version ");
+ if (nodeTag(&castNode(A_Const, lsecond(xml_expr->args))->val) == T_Null)
+ appendStringInfoString(str, "NO VALUE");
+ else
+ deparseExpr(str, lsecond(xml_expr->args));
+ if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
+ appendStringInfoString(str, ", STANDALONE YES");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
+ appendStringInfoString(str, ", STANDALONE NO");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
+ appendStringInfoString(str, ", STANDALONE NO VALUE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLSERIALIZE: /* XMLSERIALIZE(is_document, xmlval) */
+ // These are represented as XmlSerialize in raw parse trees
+ Assert(false);
+ break;
+ case IS_DOCUMENT: /* xmlval IS DOCUMENT */
+ Assert(list_length(xml_expr->args) == 1);
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, " IS DOCUMENT");
+ break;
+ }
+}
+
+static void deparseRangeTableFuncCol(StringInfo str, RangeTableFuncCol* range_table_func_col)
+{
+ appendStringInfoString(str, quote_identifier(range_table_func_col->colname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->for_ordinality)
+ {
+ appendStringInfoString(str, "FOR ORDINALITY ");
+ }
+ else
+ {
+ deparseTypeName(str, range_table_func_col->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->colexpr)
+ {
+ appendStringInfoString(str, "PATH ");
+ deparseExpr(str, range_table_func_col->colexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->coldefexpr)
+ {
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, range_table_func_col->coldefexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->is_not_null)
+ appendStringInfoString(str, "NOT NULL ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func)
+{
+ ListCell *lc;
+
+ if (range_table_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoString(str, "xmltable(");
+ if (range_table_func->namespaces)
+ {
+ appendStringInfoString(str, "xmlnamespaces(");
+ deparseXmlNamespaceList(str, range_table_func->namespaces);
+ appendStringInfoString(str, "), ");
+ }
+
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, range_table_func->rowexpr);
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, range_table_func->docexpr);
+
+ appendStringInfoString(str, " COLUMNS ");
+ foreach(lc, range_table_func->columns)
+ {
+ deparseRangeTableFuncCol(str, castNode(RangeTableFuncCol, lfirst(lc)));
+ if (lnext(range_table_func->columns, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, ") ");
+
+ if (range_table_func->alias)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_table_func->alias);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize)
+{
+ appendStringInfoString(str, "xmlserialize(");
+ switch (xml_serialize->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, xml_serialize->expr);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, xml_serialize->typeName);
+ appendStringInfoString(str, ")");
+}
+
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
+{
+ appendStringInfoString(str, "GROUPING(");
+ deparseExprList(str, grouping_func->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
+{
+ appendStringInfoString(str, "CLUSTER ");
+
+ deparseUtilityOptionList(str, cluster_stmt->params);
+
+ if (cluster_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (cluster_stmt->indexname != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(cluster_stmt->indexname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ case T_Float:
+ deparseNumericOnly(str, value);
+ break;
+ case T_String:
+ if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
+ appendStringInfoString(str, quote_identifier(value->val.str));
+ } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
+ deparseStringLiteral(str, value->val.str);
+ } else {
+ appendStringInfoString(str, value->val.str);
+ }
+ break;
+ case T_BitString:
+ if (strlen(value->val.str) >= 1 && value->val.str[0] == 'x')
+ {
+ appendStringInfoChar(str, 'x');
+ deparseStringLiteral(str, value->val.str + 1);
+ }
+ else if (strlen(value->val.str) >= 1 && value->val.str[0] == 'b')
+ {
+ appendStringInfoChar(str, 'b');
+ deparseStringLiteral(str, value->val.str + 1);
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case T_Null:
+ appendStringInfoString(str, "NULL");
+ break;
+ default:
+ elog(ERROR, "deparse: unrecognized value node type: %d",
+ (int) nodeTag(value));
+ break;
+ }
+}
+
+// "PrepareableStmt" in gram.y
+static void deparsePreparableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "RuleActionStmt" in gram.y
+static void deparseRuleActionStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "ExplainableStmt" in gram.y
+static void deparseExplainableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_CreateTableAsStmt:
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "schema_stmt" in gram.y
+static void deparseSchemaStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "stmt" in gram.y
+static void deparseStmt(StringInfo str, Node *node)
+{
+ // Note the following grammar names are missing in the list, because they
+ // get mapped to other node types:
+ //
+ // - AlterForeignTableStmt (=> AlterTableStmt)
+ // - AlterGroupStmt (=> AlterRoleStmt)
+ // - AlterCompositeTypeStmt (=> AlterTableStmt)
+ // - AnalyzeStmt (=> VacuumStmt)
+ // - CreateGroupStmt (=> CreateRoleStmt)
+ // - CreateMatViewStmt (=> CreateTableAsStmt)
+ // - CreateUserStmt (=> CreateRoleStmt)
+ // - DropCastStmt (=> DropStmt)
+ // - DropOpClassStmt (=> DropStmt)
+ // - DropOpFamilyStmt (=> DropStmt)
+ // - DropPLangStmt (=> DropPLangStmt)
+ // - DropTransformStmt (=> DropStmt)
+ // - RemoveAggrStmt (=> DropStmt)
+ // - RemoveFuncStmt (=> DropStmt)
+ // - RemoveOperStmt (=> DropStmt)
+ // - RevokeStmt (=> GrantStmt)
+ // - RevokeRoleStmt (=> GrantRoleStmt)
+ // - VariableResetStmt (=> VariableSetStmt)
+ //
+ // And the following grammar names error out in the parser:
+ // - CreateAssertionStmt (not supported yet)
+ switch (nodeTag(node))
+ {
+ case T_AlterEventTrigStmt:
+ deparseAlterEventTrigStmt(str, castNode(AlterEventTrigStmt, node));
+ break;
+ case T_AlterCollationStmt:
+ deparseAlterCollationStmt(str, castNode(AlterCollationStmt, node));
+ break;
+ case T_AlterDatabaseStmt:
+ deparseAlterDatabaseStmt(str, castNode(AlterDatabaseStmt, node));
+ break;
+ case T_AlterDatabaseSetStmt:
+ deparseAlterDatabaseSetStmt(str, castNode(AlterDatabaseSetStmt, node));
+ break;
+ case T_AlterDefaultPrivilegesStmt:
+ deparseAlterDefaultPrivilegesStmt(str, castNode(AlterDefaultPrivilegesStmt, node));
+ break;
+ case T_AlterDomainStmt:
+ deparseAlterDomainStmt(str, castNode(AlterDomainStmt, node));
+ break;
+ case T_AlterEnumStmt:
+ deparseAlterEnumStmt(str, castNode(AlterEnumStmt, node));
+ break;
+ case T_AlterExtensionStmt:
+ deparseAlterExtensionStmt(str, castNode(AlterExtensionStmt, node));
+ break;
+ case T_AlterExtensionContentsStmt:
+ deparseAlterExtensionContentsStmt(str, castNode(AlterExtensionContentsStmt, node));
+ break;
+ case T_AlterFdwStmt:
+ deparseAlterFdwStmt(str, castNode(AlterFdwStmt, node));
+ break;
+ case T_AlterForeignServerStmt:
+ deparseAlterForeignServerStmt(str, castNode(AlterForeignServerStmt, node));
+ break;
+ case T_AlterFunctionStmt:
+ deparseAlterFunctionStmt(str, castNode(AlterFunctionStmt, node));
+ break;
+ case T_AlterObjectDependsStmt:
+ deparseAlterObjectDependsStmt(str, castNode(AlterObjectDependsStmt, node));
+ break;
+ case T_AlterObjectSchemaStmt:
+ deparseAlterObjectSchemaStmt(str, castNode(AlterObjectSchemaStmt, node));
+ break;
+ case T_AlterOwnerStmt:
+ deparseAlterOwnerStmt(str, castNode(AlterOwnerStmt, node));
+ break;
+ case T_AlterOperatorStmt:
+ deparseAlterOperatorStmt(str, castNode(AlterOperatorStmt, node));
+ break;
+ case T_AlterTypeStmt:
+ deparseAlterTypeStmt(str, castNode(AlterTypeStmt, node));
+ break;
+ case T_AlterPolicyStmt:
+ deparseAlterPolicyStmt(str, castNode(AlterPolicyStmt, node));
+ break;
+ case T_AlterSeqStmt:
+ deparseAlterSeqStmt(str, castNode(AlterSeqStmt, node));
+ break;
+ case T_AlterSystemStmt:
+ deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
+ break;
+ case T_AlterTableStmt:
+ deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
+ break;
+ case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
+ deparseAlterTableSpaceOptionsStmt(str, castNode(AlterTableSpaceOptionsStmt, node));
+ break;
+ case T_AlterPublicationStmt:
+ deparseAlterPublicationStmt(str, castNode(AlterPublicationStmt, node));
+ break;
+ case T_AlterRoleSetStmt:
+ deparseAlterRoleSetStmt(str, castNode(AlterRoleSetStmt, node));
+ break;
+ case T_AlterRoleStmt:
+ deparseAlterRoleStmt(str, castNode(AlterRoleStmt, node));
+ break;
+ case T_AlterSubscriptionStmt:
+ deparseAlterSubscriptionStmt(str, castNode(AlterSubscriptionStmt, node));
+ break;
+ case T_AlterStatsStmt:
+ deparseAlterStatsStmt(str, castNode(AlterStatsStmt, node));
+ break;
+ case T_AlterTSConfigurationStmt:
+ deparseAlterTSConfigurationStmt(str, castNode(AlterTSConfigurationStmt, node));
+ break;
+ case T_AlterTSDictionaryStmt:
+ deparseAlterTSDictionaryStmt(str, castNode(AlterTSDictionaryStmt, node));
+ break;
+ case T_AlterUserMappingStmt:
+ deparseAlterUserMappingStmt(str, castNode(AlterUserMappingStmt, node));
+ break;
+ case T_CallStmt:
+ deparseCallStmt(str, castNode(CallStmt, node));
+ break;
+ case T_CheckPointStmt:
+ deparseCheckPointStmt(str, castNode(CheckPointStmt, node));
+ break;
+ case T_ClosePortalStmt:
+ deparseClosePortalStmt(str, castNode(ClosePortalStmt, node));
+ break;
+ case T_ClusterStmt:
+ deparseClusterStmt(str, castNode(ClusterStmt, node));
+ break;
+ case T_CommentStmt:
+ deparseCommentStmt(str, castNode(CommentStmt, node));
+ break;
+ case T_ConstraintsSetStmt:
+ deparseConstraintsSetStmt(str, castNode(ConstraintsSetStmt, node));
+ break;
+ case T_CopyStmt:
+ deparseCopyStmt(str, castNode(CopyStmt, node));
+ break;
+ case T_CreateAmStmt:
+ deparseCreateAmStmt(str, castNode(CreateAmStmt, node));
+ break;
+ case T_CreateTableAsStmt: // "CreateAsStmt" in gram.y
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_CreateCastStmt:
+ deparseCreateCastStmt(str, castNode(CreateCastStmt, node));
+ break;
+ case T_CreateConversionStmt:
+ deparseCreateConversionStmt(str, castNode(CreateConversionStmt, node));
+ break;
+ case T_CreateDomainStmt:
+ deparseCreateDomainStmt(str, castNode(CreateDomainStmt, node));
+ break;
+ case T_CreateExtensionStmt:
+ deparseCreateExtensionStmt(str, castNode(CreateExtensionStmt, node));
+ break;
+ case T_CreateFdwStmt:
+ deparseCreateFdwStmt(str, castNode(CreateFdwStmt, node));
+ break;
+ case T_CreateForeignServerStmt:
+ deparseCreateForeignServerStmt(str, castNode(CreateForeignServerStmt, node));
+ break;
+ case T_CreateForeignTableStmt:
+ deparseCreateForeignTableStmt(str, castNode(CreateForeignTableStmt, node));
+ break;
+ case T_CreateFunctionStmt:
+ deparseCreateFunctionStmt(str, castNode(CreateFunctionStmt, node));
+ break;
+ case T_CreateOpClassStmt:
+ deparseCreateOpClassStmt(str, castNode(CreateOpClassStmt, node));
+ break;
+ case T_CreateOpFamilyStmt:
+ deparseCreateOpFamilyStmt(str, castNode(CreateOpFamilyStmt, node));
+ break;
+ case T_CreatePublicationStmt:
+ deparseCreatePublicationStmt(str, castNode(CreatePublicationStmt, node));
+ break;
+ case T_AlterOpFamilyStmt:
+ deparseAlterOpFamilyStmt(str, castNode(AlterOpFamilyStmt, node));
+ break;
+ case T_CreatePolicyStmt:
+ deparseCreatePolicyStmt(str, castNode(CreatePolicyStmt, node));
+ break;
+ case T_CreatePLangStmt:
+ deparseCreatePLangStmt(str, castNode(CreatePLangStmt, node));
+ break;
+ case T_CreateSchemaStmt:
+ deparseCreateSchemaStmt(str, castNode(CreateSchemaStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_CreateSubscriptionStmt:
+ deparseCreateSubscriptionStmt(str, castNode(CreateSubscriptionStmt, node));
+ break;
+ case T_CreateStatsStmt:
+ deparseCreateStatsStmt(str, castNode(CreateStatsStmt, node));
+ break;
+ case T_CreateTableSpaceStmt:
+ deparseCreateTableSpaceStmt(str, castNode(CreateTableSpaceStmt, node));
+ break;
+ case T_CreateTransformStmt:
+ deparseCreateTransformStmt(str, castNode(CreateTransformStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_CreateEventTrigStmt:
+ deparseCreateEventTrigStmt(str, castNode(CreateEventTrigStmt, node));
+ break;
+ case T_CreateRoleStmt:
+ deparseCreateRoleStmt(str, castNode(CreateRoleStmt, node));
+ break;
+ case T_CreateUserMappingStmt:
+ deparseCreateUserMappingStmt(str, castNode(CreateUserMappingStmt, node));
+ break;
+ case T_CreatedbStmt:
+ deparseCreatedbStmt(str, castNode(CreatedbStmt, node));
+ break;
+ case T_DeallocateStmt:
+ deparseDeallocateStmt(str, castNode(DeallocateStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_DefineStmt:
+ deparseDefineStmt(str, castNode(DefineStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DiscardStmt:
+ deparseDiscardStmt(str, castNode(DiscardStmt, node));
+ break;
+ case T_DoStmt:
+ deparseDoStmt(str, castNode(DoStmt, node));
+ break;
+ case T_DropOwnedStmt:
+ deparseDropOwnedStmt(str, castNode(DropOwnedStmt, node));
+ break;
+ case T_DropStmt:
+ deparseDropStmt(str, castNode(DropStmt, node));
+ break;
+ case T_DropSubscriptionStmt:
+ deparseDropSubscriptionStmt(str, castNode(DropSubscriptionStmt, node));
+ break;
+ case T_DropTableSpaceStmt:
+ deparseDropTableSpaceStmt(str, castNode(DropTableSpaceStmt, node));
+ break;
+ case T_DropRoleStmt:
+ deparseDropRoleStmt(str, castNode(DropRoleStmt, node));
+ break;
+ case T_DropUserMappingStmt:
+ deparseDropUserMappingStmt(str, castNode(DropUserMappingStmt, node));
+ break;
+ case T_DropdbStmt:
+ deparseDropdbStmt(str, castNode(DropdbStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ case T_ExplainStmt:
+ deparseExplainStmt(str, castNode(ExplainStmt, node));
+ break;
+ case T_FetchStmt:
+ deparseFetchStmt(str, castNode(FetchStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_GrantRoleStmt:
+ deparseGrantRoleStmt(str, castNode(GrantRoleStmt, node));
+ break;
+ case T_ImportForeignSchemaStmt:
+ deparseImportForeignSchemaStmt(str, castNode(ImportForeignSchemaStmt, node));
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_ListenStmt:
+ deparseListenStmt(str, castNode(ListenStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_LoadStmt:
+ deparseLoadStmt(str, castNode(LoadStmt, node));
+ break;
+ case T_LockStmt:
+ deparseLockStmt(str, castNode(LockStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ case T_PrepareStmt:
+ deparsePrepareStmt(str, castNode(PrepareStmt, node));
+ break;
+ case T_ReassignOwnedStmt:
+ deparseReassignOwnedStmt(str, castNode(ReassignOwnedStmt, node));
+ break;
+ case T_ReindexStmt:
+ deparseReindexStmt(str, castNode(ReindexStmt, node));
+ break;
+ case T_RenameStmt:
+ deparseRenameStmt(str, castNode(RenameStmt, node));
+ break;
+ case T_RuleStmt:
+ deparseRuleStmt(str, castNode(RuleStmt, node));
+ break;
+ case T_SecLabelStmt:
+ deparseSecLabelStmt(str, castNode(SecLabelStmt, node));
+ break;
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_TransactionStmt:
+ deparseTransactionStmt(str, castNode(TransactionStmt, node));
+ break;
+ case T_TruncateStmt:
+ deparseTruncateStmt(str, castNode(TruncateStmt, node));
+ break;
+ case T_UnlistenStmt:
+ deparseUnlistenStmt(str, castNode(UnlistenStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_VacuumStmt:
+ deparseVacuumStmt(str, castNode(VacuumStmt, node));
+ break;
+ case T_VariableSetStmt:
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, node));
+ break;
+ case T_VariableShowStmt:
+ deparseVariableShowStmt(str, castNode(VariableShowStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ // These node types are created by DefineStmt grammar for CREATE TYPE in some cases
+ case T_CompositeTypeStmt:
+ deparseCompositeTypeStmt(str, castNode(CompositeTypeStmt, node));
+ break;
+ case T_CreateEnumStmt:
+ deparseCreateEnumStmt(str, castNode(CreateEnumStmt, node));
+ break;
+ case T_CreateRangeStmt:
+ deparseCreateRangeStmt(str, castNode(CreateRangeStmt, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
+ }
+}
+#endif
diff --git a/postgres_deparse.15.c b/postgres_deparse.15.c
new file mode 100644
index 0000000..6606305
--- /dev/null
+++ b/postgres_deparse.15.c
@@ -0,0 +1,10716 @@
+#include "pg_config.h"
+#if(PG_MAJORVERSION_NUM == 15)
+
+// From https://raw.githubusercontent.com/pganalyze/libpg_query/refs/tags/16-5.2.0/src/postgres_deparse.c
+
+// Copyright (c) 2015, Lukas Fittl
+// Copyright (c) 2016-2023, Duboce Labs, Inc. (pganalyze)
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "postgres.h"
+#include "catalog/index.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_trigger.h"
+#include "commands/trigger.h"
+#include "common/keywords.h"
+#include "common/kwlookup.h"
+#include "lib/stringinfo.h"
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "utils/builtins.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/xml.h"
+
+typedef enum DeparseNodeContext {
+ DEPARSE_NODE_CONTEXT_NONE,
+ // Parent node type (and sometimes field)
+ DEPARSE_NODE_CONTEXT_INSERT_RELATION,
+ DEPARSE_NODE_CONTEXT_INSERT_ON_CONFLICT,
+ DEPARSE_NODE_CONTEXT_UPDATE,
+ DEPARSE_NODE_CONTEXT_RETURNING,
+ DEPARSE_NODE_CONTEXT_A_EXPR,
+ DEPARSE_NODE_CONTEXT_XMLATTRIBUTES,
+ DEPARSE_NODE_CONTEXT_XMLNAMESPACES,
+ DEPARSE_NODE_CONTEXT_CREATE_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_TYPE,
+ DEPARSE_NODE_CONTEXT_SET_STATEMENT,
+ DEPARSE_NODE_CONTEXT_FUNC_EXPR,
+ // Identifier vs constant context
+ DEPARSE_NODE_CONTEXT_IDENTIFIER,
+ DEPARSE_NODE_CONTEXT_CONSTANT
+} DeparseNodeContext;
+
+static void
+removeTrailingSpace(StringInfo str)
+{
+ if (str->len >= 1 && str->data[str->len - 1] == ' ') {
+ str->len -= 1;
+ str->data[str->len] = '\0';
+ }
+}
+
+/*
+ * Append a SQL string literal representing "val" to buf.
+ *
+ * Copied here from postgres_fdw/deparse.c to avoid adding
+ * many additional dependencies.
+ */
+static void
+deparseStringLiteral(StringInfo buf, const char *val)
+{
+ const char *valptr;
+
+ /*
+ * Rather than making assumptions about the remote server's value of
+ * standard_conforming_strings, always use E'foo' syntax if there are any
+ * backslashes. This will fail on remote servers before 8.1, but those
+ * are long out of support.
+ */
+ if (strchr(val, '\\') != NULL)
+ appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
+ appendStringInfoChar(buf, '\'');
+ for (valptr = val; *valptr; valptr++)
+ {
+ char ch = *valptr;
+
+ if (SQL_STR_DOUBLE(ch, true))
+ appendStringInfoChar(buf, ch);
+ appendStringInfoChar(buf, ch);
+ }
+ appendStringInfoChar(buf, '\'');
+}
+
+// Check whether the value is a reserved keyword, to determine escaping for output
+//
+// Note that since the parser lowercases all keywords, this does *not* match when the
+// value is not all-lowercase and a reserved keyword.
+static bool
+isReservedKeyword(const char *val)
+{
+ int kwnum = ScanKeywordLookup(val, &ScanKeywords);
+ bool all_lower_case = true;
+ const char *cp;
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ (*cp >= 'a' && *cp <= 'z') ||
+ (*cp >= '0' && *cp <= '9') ||
+ (*cp == '_')))
+ {
+ all_lower_case = false;
+ break;
+ }
+ }
+
+ return all_lower_case && kwnum >= 0 && ScanKeywordCategories[kwnum] == RESERVED_KEYWORD;
+}
+
+// Returns whether the given value consists only of operator characters
+static bool
+isOp(const char *val)
+{
+ const char *cp;
+
+ Assert(strlen(val) > 0);
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ *cp == '~' ||
+ *cp == '!' ||
+ *cp == '@' ||
+ *cp == '#' ||
+ *cp == '^' ||
+ *cp == '&' ||
+ *cp == '|' ||
+ *cp == '`' ||
+ *cp == '?' ||
+ *cp == '+' ||
+ *cp == '-' ||
+ *cp == '*' ||
+ *cp == '/' ||
+ *cp == '%' ||
+ *cp == '<' ||
+ *cp == '>' ||
+ *cp == '='))
+ return false;
+ }
+
+ return true;
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt);
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause);
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context);
+static void deparseResTarget(StringInfo str, ResTarget *res_target, DeparseNodeContext context);
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt);
+static void deparseAlias(StringInfo str, Alias *alias);
+static void deparseWindowDef(StringInfo str, WindowDef* window_def);
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref);
+static void deparseSubLink(StringInfo str, SubLink* sub_link);
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context);
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr);
+static void deparseAStar(StringInfo str, A_Star* a_star);
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause);
+static void deparseSortBy(StringInfo str, SortBy* sort_by);
+static void deparseParamRef(StringInfo str, ParamRef* param_ref);
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function);
+static void deparseWithClause(StringInfo str, WithClause *with_clause);
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr);
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte);
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect);
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func);
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr * array_expr);
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr);
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context);
+static void deparseTypeName(StringInfo str, TypeName *type_name);
+static void deparseIntervalTypmods(StringInfo str, TypeName *type_name);
+static void deparseNullTest(StringInfo str, NullTest *null_test);
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr);
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when);
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection);
+static void deparseAIndices(StringInfo str, A_Indices *a_indices);
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr);
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test);
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def);
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt);
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause);
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem);
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt);
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt);
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause);
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default);
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt);
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt);
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter);
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec);
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt);
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt);
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt);
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample);
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func);
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set);
+static void deparseFuncCall(StringInfo str, FuncCall *func_call);
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr);
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr);
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize);
+static void deparseConstraint(StringInfo str, Constraint *constraint);
+static void deparseSchemaStmt(StringInfo str, Node *node);
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt);
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition);
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item);
+static void deparseAConst(StringInfo str, A_Const *a_const);
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr);
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func);
+
+static void deparsePreparableStmt(StringInfo str, Node *node);
+static void deparseRuleActionStmt(StringInfo str, Node *node);
+static void deparseExplainableStmt(StringInfo str, Node *node);
+static void deparseStmt(StringInfo str, Node *node);
+static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context);
+
+
+// "any_name" in gram.y
+static void deparseAnyName(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, parts)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipFirst(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, parts, 1)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipLast(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, parts)
+ {
+ if (lnext(parts, lc))
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (foreach_current_index(lc) < list_length(parts) - 2)
+ appendStringInfoChar(str, '.');
+ }
+ }
+}
+
+// "a_expr" / "b_expr" in gram.y
+static void deparseExpr(StringInfo str, Node *node)
+{
+ if (node == NULL)
+ return;
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Expr:
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_NullTest:
+ deparseNullTest(str, castNode(NullTest, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_BoolExpr:
+ deparseBoolExpr(str, castNode(BoolExpr, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_SetToDefault:
+ deparseSetToDefault(str, castNode(SetToDefault, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CollateClause:
+ deparseCollateClause(str, castNode(CollateClause, node));
+ break;
+ case T_CurrentOfExpr:
+ deparseCurrentOfExpr(str, castNode(CurrentOfExpr, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_BooleanTest:
+ deparseBooleanTest(str, castNode(BooleanTest, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "c_expr" in gram.y
+static void deparseCExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_A_Expr:
+ appendStringInfoChar(str, '(');
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ')');
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in c_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "expr_list" in gram.y
+static void deparseExprList(StringInfo str, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
+static void deparseColId(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "ColLabel", "attr_name"
+//
+// Note this is kept separate from ColId in case we ever want to be more
+// specific on how to handle keywords here
+static void deparseColLabel(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "SignedIconst" and "Iconst" in gram.y
+static void deparseSignedIconst(StringInfo str, Node *node)
+{
+ appendStringInfo(str, "%d", intVal(node));
+}
+
+// "indirection" and "opt_indirection" in gram.y
+static void deparseOptIndirection(StringInfo str, List *indirection, int N)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, indirection, N)
+ {
+ if (IsA(lfirst(lc), String))
+ {
+ appendStringInfoChar(str, '.');
+ deparseColLabel(str, strVal(lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Star))
+ {
+ appendStringInfoString(str, ".*");
+ }
+ else if (IsA(lfirst(lc), A_Indices))
+ {
+ deparseAIndices(str, castNode(A_Indices, lfirst(lc)));
+ }
+ else
+ {
+ // No other nodes should appear here
+ Assert(false);
+ }
+ }
+}
+
+// "role_list" in gram.y
+static void deparseRoleList(StringInfo str, List *roles)
+{
+ ListCell *lc;
+
+ foreach(lc, roles)
+ {
+ RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
+ deparseRoleSpec(str, role_spec);
+ if (lnext(roles, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SimpleTypename" in gram.y
+static void deparseSimpleTypename(StringInfo str, Node *node)
+{
+ deparseTypeName(str, castNode(TypeName, node));
+}
+
+// "NumericOnly" in gram.y
+static void deparseNumericOnly(StringInfo str, union ValUnion *value)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ appendStringInfo(str, "%d", value->ival.ival);
+ break;
+ case T_Float:
+ appendStringInfoString(str, value->sval.sval);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "NumericOnly_list" in gram.y
+static void deparseNumericOnlyList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseNumericOnly(str, (union ValUnion *) lfirst(lc));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SeqOptElem" in gram.y
+static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseSimpleTypename(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cache") == 0)
+ {
+ appendStringInfoString(str, "CACHE ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NO CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "increment") == 0)
+ {
+ appendStringInfoString(str, "INCREMENT ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MAXVALUE ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MAXVALUE");
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MINVALUE ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MINVALUE");
+ }
+ else if (strcmp(def_elem->defname, "owned_by") == 0)
+ {
+ appendStringInfoString(str, "OWNED BY ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "sequence_name") == 0)
+ {
+ appendStringInfoString(str, "SEQUENCE NAME ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "start") == 0)
+ {
+ appendStringInfoString(str, "START ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "SeqOptList" in gram.y
+static void deparseSeqOptList(StringInfo str, List *options)
+{
+ ListCell *lc;
+ Assert(list_length(options) > 0);
+ foreach (lc, options)
+ {
+ deparseSeqOptElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "OptSeqOptList" in gram.y
+static void deparseOptSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ deparseSeqOptList(str, options);
+}
+
+// "OptParenthesizedSeqOptList" in gram.y
+static void deparseOptParenthesizedSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseSeqOptList(str, options);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "opt_drop_behavior" in gram.y
+static void deparseOptDropBehavior(StringInfo str, DropBehavior behavior)
+{
+ switch (behavior)
+ {
+ case DROP_RESTRICT:
+ // Default
+ break;
+ case DROP_CASCADE:
+ appendStringInfoString(str, "CASCADE ");
+ break;
+ }
+}
+
+// "any_operator" in gram.y
+static void deparseAnyOperator(StringInfo str, List *op)
+{
+ Assert(isOp(strVal(llast(op))));
+ if (list_length(op) == 2)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(linitial(op))));
+ appendStringInfoChar(str, '.');
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else if (list_length(op) == 1)
+ {
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "qual_Op" and "qual_all_Op" in gram.y
+static void deparseQualOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// "subquery_Op" in gram.y
+static void deparseSubqueryOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
+ {
+ appendStringInfoString(str, "LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
+ {
+ appendStringInfoString(str, "NOT LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
+ {
+ appendStringInfoString(str, "ILIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
+ {
+ appendStringInfoString(str, "NOT ILIKE");
+ }
+ else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// Not present directly in gram.y (usually matched by ColLabel)
+static void deparseGenericDefElemName(StringInfo str, const char *in)
+{
+ Assert(in != NULL);
+ char *val = pstrdup(in);
+ for (unsigned char *p = (unsigned char *) val; *p; p++)
+ *p = pg_toupper(*p);
+ appendStringInfoString(str, val);
+ pfree(val);
+}
+
+// "def_arg" and "operator_def_arg" in gram.y
+static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
+{
+ if (IsA(arg, TypeName)) // func_type
+ {
+ deparseTypeName(str, castNode(TypeName, arg));
+ }
+ else if (IsA(arg, List)) // qual_all_Op
+ {
+ List *l = castNode(List, arg);
+ Assert(list_length(l) == 1 || list_length(l) == 2);
+
+ // Schema qualified operator
+ if (list_length(l) == 2)
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, l);
+ appendStringInfoChar(str, ')');
+ }
+ else if (list_length(l) == 1)
+ {
+ appendStringInfoString(str, strVal(linitial(l)));
+ }
+ }
+ else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
+ {
+ deparseValue(str, (union ValUnion *) arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (IsA(arg, String))
+ {
+ char *s = strVal(arg);
+ if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) // NONE
+ {
+ appendStringInfoString(str, "NONE");
+ }
+ else if (isReservedKeyword(s)) // reserved_keyword
+ {
+ appendStringInfoString(str, s);
+ }
+ else // Sconst
+ {
+ deparseStringLiteral(str, s);
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "definition" in gram.y
+static void deparseDefinition(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL) {
+ appendStringInfoString(str, " = ");
+ deparseDefArg(str, def_elem->arg, false);
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "opt_definition" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptDefinition(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseDefinition(str, options);
+ }
+}
+
+// "create_generic_options" in gram.y
+static void deparseCreateGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ if (options == NULL)
+ return;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ")");
+}
+
+// "common_func_opt_item" in gram.y
+static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "strict") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "strict") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "CALLED ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
+ {
+ appendStringInfoString(str, "IMMUTABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
+ {
+ appendStringInfoString(str, "STABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
+ {
+ appendStringInfoString(str, "VOLATILE");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "SECURITY DEFINER");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "SECURITY INVOKER");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOT LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "cost") == 0)
+ {
+ appendStringInfoString(str, "COST ");
+ deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "rows") == 0)
+ {
+ appendStringInfoString(str, "ROWS ");
+ deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "support") == 0)
+ {
+ appendStringInfoString(str, "SUPPORT ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
+ {
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "parallel") == 0)
+ {
+ appendStringInfoString(str, "PARALLEL ");
+ appendStringInfoString(str, quote_identifier(strVal(def_elem->arg)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "NonReservedWord_or_Sconst" in gram.y
+//
+// Note since both identifiers and string constants are allowed here, we
+// currently always return an identifier, except:
+//
+// 1) when the string is empty (since an empty identifier can't be scanned)
+// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
+static void deparseNonReservedWordOrSconst(StringInfo str, const char *val)
+{
+ if (strlen(val) == 0)
+ appendStringInfoString(str, "''");
+ else if (strlen(val) >= NAMEDATALEN)
+ deparseStringLiteral(str, val);
+ else
+ appendStringInfoString(str, quote_identifier(val));
+}
+
+// "func_as" in gram.y
+static void deparseFuncAs(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ char *strval = strVal(lfirst(lc));
+ if (strstr(strval, "$$") == NULL)
+ {
+ appendStringInfoString(str, "$$");
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, "$$");
+ }
+ else
+ {
+ deparseStringLiteral(str, strval);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createfunc_opt_item" in gram.y
+static void deparseCreateFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc = NULL;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseFuncAs(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "transform") == 0)
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, "TRANSFORM ");
+ foreach (lc, l)
+ {
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ else if (strcmp(def_elem->defname, "window") == 0)
+ {
+ appendStringInfoString(str, "WINDOW");
+ }
+ else
+ {
+ deparseCommonFuncOptItem(str, def_elem);
+ }
+}
+
+// "alter_generic_options" in gram.y
+static void deparseAlterGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ switch (def_elem->defaction)
+ {
+ case DEFELEM_UNSPEC:
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ break;
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "func_name" in gram.y
+static void deparseFuncName(StringInfo str, List *func_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, func_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(func_name, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "function_with_argtypes" in gram.y
+static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc;
+ deparseFuncName(str, object_with_args->objname);
+
+ if (!object_with_args->args_unspecified)
+ {
+ appendStringInfoChar(str, '(');
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "function_with_argtypes_list" in gram.y
+static void deparseFunctionWithArgtypesList(StringInfo str, List *l)
+{
+ ListCell *lc;
+
+ foreach(lc, l)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "operator_with_argtypes" in gram.y
+static void deparseOperatorWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ deparseAnyOperator(str, object_with_args->objname);
+
+ Assert(list_length(object_with_args->objargs) == 2);
+ appendStringInfoChar(str, '(');
+ if (linitial(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, linitial(object_with_args->objargs)));
+ appendStringInfoString(str, ", ");
+ if (lsecond(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, lsecond(object_with_args->objargs)));
+ appendStringInfoChar(str, ')');
+}
+
+// "aggr_args" in gram.y
+static void deparseAggrArgs(StringInfo str, List *aggr_args)
+{
+ Assert(list_length(aggr_args) == 2);
+
+ ListCell *lc = NULL;
+ List *args = linitial(aggr_args);
+ int order_by_pos = intVal(lsecond(aggr_args));
+
+ appendStringInfoChar(str, '(');
+ if (args == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, args)
+ {
+ if (foreach_current_index(lc) == order_by_pos)
+ {
+ if (foreach_current_index(lc) > 0)
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, "ORDER BY ");
+ }
+ else if (foreach_current_index(lc) > 0)
+ {
+ appendStringInfoString(str, ", ");
+ }
+
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ }
+
+ // Repeat the last direct arg as a ordered arg to handle the
+ // simplification done by makeOrderedSetArgs in gram.y
+ if (order_by_pos == list_length(args))
+ {
+ appendStringInfoString(str, " ORDER BY ");
+ deparseFunctionParameter(str, castNode(FunctionParameter, llast(args)));
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "aggregate_with_argtypes" in gram.y
+static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc = NULL;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ appendStringInfoChar(str, '(');
+ if (object_with_args->objargs == NULL && object_with_args->objfuncargs == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "columnList" in gram.y
+static void deparseColumnList(StringInfo str, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(columns, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptTemp" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptTemp(StringInfo str, char relpersistence)
+{
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_PERMANENT:
+ // Default
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ appendStringInfoString(str, "UNLOGGED ");
+ break;
+ case RELPERSISTENCE_TEMP:
+ appendStringInfoString(str, "TEMPORARY ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+// "relation_expr_list" in gram.y
+static void deparseRelationExprList(StringInfo str, List *relation_exprs)
+{
+ ListCell *lc = NULL;
+ foreach(lc, relation_exprs)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(relation_exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "handler_name" in gram.y
+static void deparseHandlerName(StringInfo str, List *handler_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, handler_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(handler_name, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "fdw_options" in gram.y
+static void deparseFdwOptions(StringInfo str, List *fdw_options)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, fdw_options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO HANDLER ");
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO VALIDATOR ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(fdw_options, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "type_list" in gram.y
+static void deparseTypeList(StringInfo str, List *type_list)
+{
+ ListCell *lc = NULL;
+ foreach(lc, type_list)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(type_list, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_boolean_or_string" in gram.y
+static void deparseOptBooleanOrString(StringInfo str, char *s)
+{
+ if (s == NULL)
+ return; // No value set
+ else if (strcmp(s, "true") == 0)
+ appendStringInfoString(str, "TRUE");
+ else if (strcmp(s, "false") == 0)
+ appendStringInfoString(str, "FALSE");
+ else if (strcmp(s, "on") == 0)
+ appendStringInfoString(str, "ON");
+ else if (strcmp(s, "off") == 0)
+ appendStringInfoString(str, "OFF");
+ else
+ deparseNonReservedWordOrSconst(str, s);
+}
+
+static void deparseOptBoolean(StringInfo str, Node *node)
+{
+ if (node == NULL)
+ {
+ return;
+ }
+
+ switch (nodeTag(node))
+ {
+ case T_String:
+ appendStringInfo(str, " %s", strVal(node));
+ break;
+ case T_Integer:
+ appendStringInfo(str, " %d", intVal(node));
+ break;
+ case T_Boolean:
+ appendStringInfo(str, " %s", boolVal(node) ? "TRUE" : "FALSE");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+bool optBooleanValue(Node *node)
+{
+ if (node == NULL)
+ {
+ return true;
+ }
+
+ switch (nodeTag(node))
+ {
+ case T_String: {
+ // Longest valid string is "off\0"
+ char lower[4];
+ strncpy(lower, strVal(node), 4);
+ lower[3] = 0;
+
+ if (strcmp(lower, "on") == 0) {
+ return true;
+ } else if (strcmp(lower, "off") == 0) {
+ return false;
+ }
+
+ // No sane way to handle this.
+ return false;
+ }
+ case T_Integer:
+ return intVal(node) != 0;
+ case T_Boolean:
+ return boolVal(node);
+ default:
+ Assert(false);
+ return false;
+ }
+}
+
+// "var_name"
+//
+// Note this is kept separate from ColId in case we want to improve the
+// output of namespaced variable names
+static void deparseVarName(StringInfo str, char *s)
+{
+ deparseColId(str, s);
+}
+
+// "var_list"
+static void deparseVarList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, lfirst(lc));
+ if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
+ deparseNumericOnly(str, (union ValUnion *) &a_const->val);
+ else if (IsA(&a_const->val, String))
+ deparseOptBooleanOrString(str, strVal(&a_const->val));
+ else
+ Assert(false);
+ }
+ else if (IsA(lfirst(lc), TypeCast))
+ {
+ deparseTypeCast(str, castNode(TypeCast, lfirst(lc)), DEPARSE_NODE_CONTEXT_SET_STATEMENT);
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "transaction_mode_list" in gram.y
+static void deparseTransactionModeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "transaction_isolation") == 0)
+ {
+ char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
+ appendStringInfoString(str, "ISOLATION LEVEL ");
+ if (strcmp(s, "read uncommitted") == 0)
+ appendStringInfoString(str, "READ UNCOMMITTED");
+ else if (strcmp(s, "read committed") == 0)
+ appendStringInfoString(str, "READ COMMITTED");
+ else if (strcmp(s, "repeatable read") == 0)
+ appendStringInfoString(str, "REPEATABLE READ");
+ else if (strcmp(s, "serializable") == 0)
+ appendStringInfoString(str, "SERIALIZABLE");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "READ ONLY");
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "READ WRITE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "DEFERRABLE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "NOT DEFERRABLE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "alter_identity_column_option_list" in gram.y
+static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "generated") == 0)
+ {
+ appendStringInfoString(str, "SET GENERATED ");
+ if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
+ appendStringInfoString(str, "ALWAYS");
+ else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+ appendStringInfoString(str, "BY DEFAULT");
+ else
+ Assert(false);
+ }
+ else
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSeqOptElem(str, def_elem);
+ }
+ if (lnext(l, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "reloptions" in gram.y
+static void deparseRelOptions(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (def_elem->defnamespace != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defnamespace));
+ appendStringInfoChar(str, '.');
+ }
+ if (def_elem->defname != NULL)
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->defname != NULL && def_elem->arg != NULL)
+ appendStringInfoChar(str, '=');
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, false);
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "OptWith" and "opt_reloptions" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptWith(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseRelOptions(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "target_list" and "opt_target_list" in gram.y
+static void deparseTargetList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+
+ if (res_target->val == NULL)
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
+ else if (IsA(res_target->val, ColumnRef))
+ deparseColumnRef(str, castNode(ColumnRef, res_target->val));
+ else
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL) {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "insert_column_list" in gram.y
+static void deparseInsertColumnList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->name != NULL);
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ deparseOptIndirection(str, res_target->indirection, 0);
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_attribute_list" in gram.y
+static void deparseXmlAttributeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_namespace_list" in gram.y
+static void deparseXmlNamespaceList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (res_target->name == NULL)
+ appendStringInfoString(str, "DEFAULT ");
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "table_ref" in gram.y
+static void deparseTableRef(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_RangeVar:
+ deparseRangeVar(str, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_RangeTableSample:
+ deparseRangeTableSample(str, castNode(RangeTableSample, node));
+ break;
+ case T_RangeFunction:
+ deparseRangeFunction(str, castNode(RangeFunction, node));
+ break;
+ case T_RangeTableFunc:
+ deparseRangeTableFunc(str, castNode(RangeTableFunc, node));
+ break;
+ case T_RangeSubselect:
+ deparseRangeSubselect(str, castNode(RangeSubselect, node));
+ break;
+ case T_JoinExpr:
+ deparseJoinExpr(str, castNode(JoinExpr, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "from_list" in gram.y
+static void deparseFromList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseTableRef(str, lfirst(lc));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "from_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseFromClause(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseFromList(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "where_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereClause(StringInfo str, Node *node)
+{
+ if (node != NULL)
+ {
+ appendStringInfoString(str, "WHERE ");
+ deparseExpr(str, node);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "group_by_list" in gram.y
+static void deparseGroupByList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), GroupingSet))
+ deparseGroupingSet(str, castNode(GroupingSet, lfirst(lc)));
+ else
+ deparseExpr(str, lfirst(lc));
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "set_target" in gram.y
+static void deparseSetTarget(StringInfo str, ResTarget *res_target)
+{
+ Assert(res_target->name != NULL);
+ deparseColId(str, res_target->name);
+ deparseOptIndirection(str, res_target->indirection, 0);
+}
+
+// "any_name_list" in gram.y
+static void deparseAnyNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseAnyName(str, castNode(List, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "name_list" in gram.y
+static void deparseNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseColId(str, strVal(lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_sort_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptSortClause(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "ORDER BY ");
+
+ foreach(lc, l)
+ {
+ deparseSortBy(str, castNode(SortBy, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "func_arg_expr" in gram.y
+static void deparseFuncArgExpr(StringInfo str, Node *node)
+{
+ if (IsA(node, NamedArgExpr))
+ {
+ NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
+ appendStringInfoString(str, named_arg_expr->name);
+ appendStringInfoString(str, " := ");
+ deparseExpr(str, (Node *) named_arg_expr->arg);
+ }
+ else
+ {
+ deparseExpr(str, node);
+ }
+}
+
+// "set_clause_list" in gram.y
+static void deparseSetClauseList(StringInfo str, List *target_list)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ int skip_next_n_elems = 0;
+
+ Assert(list_length(target_list) > 0);
+
+ foreach(lc, target_list)
+ {
+ if (skip_next_n_elems > 0)
+ {
+ skip_next_n_elems--;
+ continue;
+ }
+
+ if (foreach_current_index(lc) != 0)
+ appendStringInfoString(str, ", ");
+
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (IsA(res_target->val, MultiAssignRef))
+ {
+ MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
+ appendStringInfoString(str, "(");
+ for_each_cell(lc2, target_list, lc)
+ {
+ deparseSetTarget(str, castNode(ResTarget, lfirst(lc2)));
+ if (foreach_current_index(lc2) == r->ncolumns - 1) // Last element in this multi-assign
+ break;
+ else if (lnext(target_list, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") = ");
+ deparseExpr(str, r->source);
+ skip_next_n_elems = r->ncolumns - 1;
+ }
+ else
+ {
+ deparseSetTarget(str, res_target);
+ appendStringInfoString(str, " = ");
+ deparseExpr(str, res_target->val);
+ }
+ }
+}
+
+// "func_expr_windowless" in gram.y
+static void deparseFuncExprWindowless(StringInfo str, Node* node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_FUNC_EXPR);
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "opt_collate" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptCollate(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "index_elem" in gram.y
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem)
+{
+ if (index_elem->name != NULL)
+ {
+ deparseColId(str, index_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (index_elem->expr != NULL)
+ {
+ switch (nodeTag(index_elem->expr))
+ {
+ // Simple function calls can be written without wrapping parens
+ case T_FuncCall: // func_application
+ case T_SQLValueFunction: // func_expr_common_subexpr
+ case T_CoalesceExpr: // func_expr_common_subexpr
+ case T_MinMaxExpr: // func_expr_common_subexpr
+ case T_XmlExpr: // func_expr_common_subexpr
+ case T_XmlSerialize: // func_expr_common_subexpr
+ deparseFuncExprWindowless(str, index_elem->expr);
+ appendStringInfoString(str, " ");
+ break;
+ default:
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, index_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseOptCollate(str, index_elem->collation);
+
+ if (list_length(index_elem->opclass) > 0)
+ {
+ deparseAnyName(str, index_elem->opclass);
+
+ if (list_length(index_elem->opclassopts) > 0)
+ deparseRelOptions(str, index_elem->opclassopts);
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (index_elem->ordering)
+ {
+ case SORTBY_DEFAULT:
+ // Default
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ // Not allowed in CREATE INDEX
+ Assert(false);
+ break;
+ }
+
+ switch (index_elem->nulls_ordering)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ // Default
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+// "qualified_name_list" in gram.y
+static void deparseQualifiedNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptInherit" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptInherit(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "INHERITS (");
+ deparseQualifiedNameList(str, l);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+// "privilege_target" in gram.y
+static void deparsePrivilegeTarget(StringInfo str, GrantTargetType targtype, ObjectType objtype, List *objs)
+{
+ switch (targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "FOREIGN SERVER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyNameList(str, objs);
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnlyList(str, objs);
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "ALL TABLES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "ALL SEQUENCES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "ALL FUNCTIONS IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "ALL PROCEDURES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ALL ROUTINES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_DEFAULTS: // defacl_privilege_target
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLES");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTIONS");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPES");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMAS");
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ }
+}
+
+// "opclass_item_list" in gram.y
+static void deparseOpclassItemList(StringInfo str, List *items)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, items)
+ {
+ deparseCreateOpClassItem(str, castNode(CreateOpClassItem, lfirst(lc)));
+ if (lnext(items, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createdb_opt_list" in gram.y
+static void deparseCreatedbOptList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "connection_limit") == 0)
+ appendStringInfoString(str, "CONNECTION LIMIT");
+ else
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ appendStringInfoString(str, "DEFAULT");
+ else if (IsA(def_elem->arg, Integer))
+ deparseSignedIconst(str, def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+
+ if (lnext(l, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "utility_option_list" in gram.y
+static void deparseUtilityOptionList(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ if (def_elem->arg != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ else
+ Assert(false);
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
+{
+ const ListCell *lc = NULL;
+ const ListCell *lc2 = NULL;
+
+ if (stmt->withClause)
+ {
+ deparseWithClause(str, stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (stmt->op) {
+ case SETOP_NONE:
+ if (list_length(stmt->valuesLists) > 0)
+ {
+ const ListCell *lc;
+ appendStringInfoString(str, "VALUES ");
+
+ foreach(lc, stmt->valuesLists)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, lfirst(lc));
+ appendStringInfoChar(str, ')');
+ if (lnext(stmt->valuesLists, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ }
+
+ appendStringInfoString(str, "SELECT ");
+
+ if (list_length(stmt->targetList) > 0)
+ {
+ if (stmt->distinctClause != NULL)
+ {
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
+ {
+ appendStringInfoString(str, "ON (");
+ deparseExprList(str, stmt->distinctClause);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ deparseTargetList(str, stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->intoClause != NULL)
+ {
+ appendStringInfoString(str, "INTO ");
+ deparseOptTemp(str, stmt->intoClause->rel->relpersistence);
+ deparseIntoClause(str, stmt->intoClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, stmt->fromClause);
+ deparseWhereClause(str, stmt->whereClause);
+
+ if (list_length(stmt->groupClause) > 0)
+ {
+ appendStringInfoString(str, "GROUP BY ");
+ if (stmt->groupDistinct)
+ appendStringInfoString(str, "DISTINCT ");
+ deparseGroupByList(str, stmt->groupClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->havingClause != NULL)
+ {
+ appendStringInfoString(str, "HAVING ");
+ deparseExpr(str, stmt->havingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->windowClause != NULL)
+ {
+ appendStringInfoString(str, "WINDOW ");
+ foreach(lc, stmt->windowClause)
+ {
+ WindowDef *window_def = castNode(WindowDef, lfirst(lc));
+ Assert(window_def->name != NULL);
+ appendStringInfoString(str, window_def->name);
+ appendStringInfoString(str, " AS ");
+ deparseWindowDef(str, window_def);
+ if (lnext(stmt->windowClause, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case SETOP_UNION:
+ case SETOP_INTERSECT:
+ case SETOP_EXCEPT:
+ {
+ bool need_larg_parens =
+ list_length(stmt->larg->sortClause) > 0 ||
+ stmt->larg->limitOffset != NULL ||
+ stmt->larg->limitCount != NULL ||
+ list_length(stmt->larg->lockingClause) > 0 ||
+ stmt->larg->withClause != NULL ||
+ stmt->larg->op != SETOP_NONE;
+ bool need_rarg_parens =
+ list_length(stmt->rarg->sortClause) > 0 ||
+ stmt->rarg->limitOffset != NULL ||
+ stmt->rarg->limitCount != NULL ||
+ list_length(stmt->rarg->lockingClause) > 0 ||
+ stmt->rarg->withClause != NULL ||
+ stmt->rarg->op != SETOP_NONE;
+ if (need_larg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->larg);
+ if (need_larg_parens)
+ appendStringInfoChar(str, ')');
+ switch (stmt->op)
+ {
+ case SETOP_UNION:
+ appendStringInfoString(str, " UNION ");
+ break;
+ case SETOP_INTERSECT:
+ appendStringInfoString(str, " INTERSECT ");
+ break;
+ case SETOP_EXCEPT:
+ appendStringInfoString(str, " EXCEPT ");
+ break;
+ default:
+ Assert(false);
+ }
+ if (stmt->all)
+ appendStringInfoString(str, "ALL ");
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ }
+
+ deparseOptSortClause(str, stmt->sortClause);
+
+ if (stmt->limitCount != NULL)
+ {
+ if (stmt->limitOption == LIMIT_OPTION_COUNT)
+ appendStringInfoString(str, "LIMIT ");
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ appendStringInfoString(str, "FETCH FIRST ");
+
+ if (IsA(stmt->limitCount, A_Const) && castNode(A_Const, stmt->limitCount)->isnull)
+ appendStringInfoString(str, "ALL");
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ deparseCExpr(str, stmt->limitCount);
+ else
+ deparseExpr(str, stmt->limitCount);
+
+ appendStringInfoChar(str, ' ');
+
+ if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ appendStringInfoString(str, "ROWS WITH TIES ");
+ }
+
+ if (stmt->limitOffset != NULL)
+ {
+ appendStringInfoString(str, "OFFSET ");
+ deparseExpr(str, stmt->limitOffset);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(stmt->lockingClause) > 0)
+ {
+ foreach(lc, stmt->lockingClause)
+ {
+ deparseLockingClause(str, castNode(LockingClause, lfirst(lc)));
+ if (lnext(stmt->lockingClause, lc))
+ appendStringInfoString(str, " ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause)
+{
+ ListCell *lc;
+
+ deparseRangeVar(str, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE); /* target relation name */
+
+ if (list_length(into_clause->colNames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, into_clause->colNames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (into_clause->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(into_clause->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptWith(str, into_clause->options);
+
+ switch (into_clause->onCommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (into_clause->tableSpaceName != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(into_clause->tableSpaceName));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context)
+{
+ if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ONLY ");
+
+ if (range_var->catalogname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->catalogname));
+ appendStringInfoChar(str, '.');
+ }
+
+ if (range_var->schemaname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->schemaname));
+ appendStringInfoChar(str, '.');
+ }
+
+ Assert(range_var->relname != NULL);
+ appendStringInfoString(str, quote_identifier(range_var->relname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_var->alias != NULL)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_var->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt)
+{
+ if (raw_stmt->stmt == NULL)
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
+
+ deparseStmt(str, raw_stmt->stmt);
+}
+
+static void deparseAlias(StringInfo str, Alias *alias)
+{
+ appendStringInfoString(str, quote_identifier(alias->aliasname));
+
+ if (list_length(alias->colnames) > 0)
+ {
+ const ListCell *lc = NULL;
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, alias->colnames);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseAConst(StringInfo str, A_Const *a_const)
+{
+ union ValUnion *val = a_const->isnull ? NULL : &a_const->val;
+ deparseValue(str, val, DEPARSE_NODE_CONTEXT_CONSTANT);
+}
+
+static void deparseFuncCall(StringInfo str, FuncCall *func_call)
+{
+ const ListCell *lc = NULL;
+
+ Assert(list_length(func_call->funcname) > 0);
+
+ if (list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "OVERLAY(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PLACING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "substring") == 0)
+ {
+ /*
+ * "SUBSTRING" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.substring)
+ */
+ Assert(list_length(func_call->args) == 2 || list_length(func_call->args) == 3);
+ appendStringInfoString(str, "SUBSTRING(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lsecond(func_call->args));
+ if (list_length(func_call->args) == 3)
+ {
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lthird(func_call->args));
+ }
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "position") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "POSITION" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.position)
+ * Note that the first and second arguments are switched in this format
+ */
+ appendStringInfoString(str, "POSITION(");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " IN ");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 3)
+ {
+ /*
+ * "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "overlay(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " placing ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " from ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "pg_collation_for") == 0 &&
+ list_length(func_call->args) == 1)
+ {
+ /*
+ * "collation for" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "collation for (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "extract") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "EXTRACT" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.extract)
+ */
+ appendStringInfoString(str, "extract (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlaps") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * "OVERLAPS" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlaps)
+ * format: (start_1, end_1) overlaps (start_2, end_2)
+ */
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, ") ");
+
+ appendStringInfoString(str, "overlaps ");
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoString(str, ") ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ (
+ strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0
+ ))
+ {
+ /*
+ * "TRIM " is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.ltrim)
+ * Note that the first and second arguments are switched in this format
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ appendStringInfoString(str, "TRIM (");
+ if (strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0)
+ appendStringInfoString(str, "LEADING ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0)
+ appendStringInfoString(str, "BOTH ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0)
+ appendStringInfoString(str, "TRAILING ");
+
+ if (list_length(func_call->args) == 2)
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "timezone") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "AT TIME ZONE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.timezone)
+ * Note that the arguments are swapped in this case
+ */
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " AT TIME ZONE ");
+ deparseExpr(str, linitial(func_call->args));
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "normalize") == 0)
+ {
+ /*
+ * "NORMALIZE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.normalize)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ appendStringInfoString(str, "normalize (");
+
+ deparseExpr(str, linitial(func_call->args));
+ if (list_length(func_call->args) == 2)
+ {
+ appendStringInfoString(str, ", ");
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "is_normalized") == 0)
+ {
+ /*
+ * "IS NORMALIZED" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.is_normalized)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " IS ");
+ if (list_length(func_call->args) == 2)
+ {
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ appendStringInfoString(str, " NORMALIZED ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "xmlexists") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ appendStringInfoString(str, "xmlexists (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ deparseFuncName(str, func_call->funcname);
+ appendStringInfoChar(str, '(');
+
+ if (func_call->agg_distinct)
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (func_call->agg_star)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (list_length(func_call->args) > 0)
+ {
+ foreach(lc, func_call->args)
+ {
+ if (func_call->func_variadic && !lnext(func_call->args, lc))
+ appendStringInfoString(str, "VARIADIC ");
+ deparseFuncArgExpr(str, lfirst(lc));
+ if (lnext(func_call->args, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (func_call->agg_order != NULL && !func_call->agg_within_group)
+ {
+ deparseOptSortClause(str, func_call->agg_order);
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+
+ if (func_call->agg_order != NULL && func_call->agg_within_group)
+ {
+ appendStringInfoString(str, "WITHIN GROUP (");
+ deparseOptSortClause(str, func_call->agg_order);
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->agg_filter)
+ {
+ appendStringInfoString(str, "FILTER (WHERE ");
+ deparseExpr(str, func_call->agg_filter);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->over)
+ {
+ appendStringInfoString(str, "OVER ");
+ if (func_call->over->name)
+ appendStringInfoString(str, func_call->over->name);
+ else
+ deparseWindowDef(str, func_call->over);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseWindowDef(StringInfo str, WindowDef* window_def)
+{
+ ListCell *lc;
+
+ // The parent node is responsible for outputting window_def->name
+
+ appendStringInfoChar(str, '(');
+
+ if (window_def->refname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(window_def->refname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(window_def->partitionClause) > 0)
+ {
+ appendStringInfoString(str, "PARTITION BY ");
+ deparseExprList(str, window_def->partitionClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptSortClause(str, window_def->orderClause);
+
+ if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
+ {
+ if (window_def->frameOptions & FRAMEOPTION_RANGE)
+ appendStringInfoString(str, "RANGE ");
+ else if (window_def->frameOptions & FRAMEOPTION_ROWS)
+ appendStringInfoString(str, "ROWS ");
+ else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
+ appendStringInfoString(str, "GROUPS ");
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ appendStringInfoString(str, "BETWEEN ");
+
+ // frame_start
+ if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ {
+ appendStringInfoString(str, "UNBOUNDED PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ {
+ appendStringInfoString(str, "AND ");
+
+ // frame_end
+ if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
+ {
+ appendStringInfoString(str, "UNBOUNDED FOLLOWING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
+ appendStringInfoString(str, "EXCLUDE CURRENT ROW ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
+ appendStringInfoString(str, "EXCLUDE GROUP ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
+ appendStringInfoString(str, "EXCLUDE TIES ");
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref)
+{
+ Assert(list_length(column_ref->fields) >= 1);
+
+ if (IsA(linitial(column_ref->fields), A_Star))
+ deparseAStar(str, castNode(A_Star, linitial(column_ref->fields)));
+ else if (IsA(linitial(column_ref->fields), String))
+ deparseColLabel(str, strVal(linitial(column_ref->fields)));
+
+ deparseOptIndirection(str, column_ref->fields, 1);
+}
+
+static void deparseSubLink(StringInfo str, SubLink* sub_link)
+{
+ switch (sub_link->subLinkType) {
+ case EXISTS_SUBLINK:
+ appendStringInfoString(str, "EXISTS (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ALL_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ALL (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ANY_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ if (list_length(sub_link->operName) > 0)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ANY ");
+ }
+ else
+ {
+ appendStringInfoString(str, " IN ");
+ }
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ROWCOMPARE_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case EXPR_SUBLINK:
+ appendStringInfoString(str, "(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case MULTIEXPR_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case ARRAY_SUBLINK:
+ appendStringInfoString(str, "ARRAY(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case CTE_SUBLINK: /* for SubPlans only */
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context)
+{
+ ListCell *lc;
+ char *name;
+
+ bool need_lexpr_parens = a_expr->lexpr != NULL && (IsA(a_expr->lexpr, BoolExpr) || IsA(a_expr->lexpr, BooleanTest) || IsA(a_expr->lexpr, NullTest) || IsA(a_expr->lexpr, A_Expr));
+ bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, BooleanTest) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
+
+ switch (a_expr->kind) {
+ case AEXPR_OP: /* normal operator */
+ {
+ bool need_outer_parens = context == DEPARSE_NODE_CONTEXT_A_EXPR;
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, '(');
+ if (a_expr->lexpr != NULL)
+ {
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ deparseQualOp(str, a_expr->name);
+ if (a_expr->rexpr != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ }
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, ')');
+ }
+ return;
+ case AEXPR_OP_ANY: /* scalar op ANY (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ANY(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OP_ALL: /* scalar op ALL (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ALL(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoString(str, " IS DISTINCT FROM ");
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, " IS NOT DISTINCT FROM ");
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_NULLIF: /* NULLIF - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ appendStringInfoString(str, "NULLIF(");
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IN ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "NOT IN ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ if (IsA(a_expr->rexpr, SubLink))
+ deparseSubLink(str, castNode(SubLink, a_expr->rexpr));
+ else
+ deparseExprList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~~") == 0) {
+ appendStringInfoString(str, "LIKE ");
+ } else if (strcmp(name, "!~~") == 0) {
+ appendStringInfoString(str, "NOT LIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~~*") == 0) {
+ appendStringInfoString(str, "ILIKE ");
+ } else if (strcmp(name, "!~~*") == 0) {
+ appendStringInfoString(str, "NOT ILIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~") == 0) {
+ appendStringInfoString(str, "SIMILAR TO ");
+ } else if (strcmp(name, "!~") == 0) {
+ appendStringInfoString(str, "NOT SIMILAR TO ");
+ } else {
+ Assert(false);
+ }
+
+ FuncCall *n = castNode(FuncCall, a_expr->rexpr);
+ Assert(list_length(n->funcname) == 2);
+ Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
+ Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
+ Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
+
+ deparseExpr(str, linitial(n->args));
+ if (list_length(n->args) == 2)
+ {
+ appendStringInfoString(str, " ESCAPE ");
+ deparseExpr(str, lsecond(n->args));
+ }
+
+ return;
+ case AEXPR_BETWEEN: /* name must be "BETWEEN" */
+ case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
+ case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
+ case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, strVal(linitial(a_expr->name)));
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, castNode(List, a_expr->rexpr)) {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(castNode(List, a_expr->rexpr), lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ }
+}
+
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr)
+{
+ const ListCell *lc = NULL;
+ switch (bool_expr->boolop)
+ {
+ case AND_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(bool_expr->args, lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case OR_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(bool_expr->args, lc))
+ appendStringInfoString(str, " OR ");
+ }
+ return;
+ case NOT_EXPR:
+ Assert(list_length(bool_expr->args) == 1);
+ bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
+ appendStringInfoString(str, "NOT ");
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(bool_expr->args));
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ }
+}
+
+static void deparseAStar(StringInfo str, A_Star *a_star)
+{
+ appendStringInfoChar(str, '*');
+}
+
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause)
+{
+ ListCell *lc;
+ if (collate_clause->arg != NULL)
+ {
+ bool need_parens = IsA(collate_clause->arg, A_Expr);
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, collate_clause->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, collate_clause->collname);
+}
+
+static void deparseSortBy(StringInfo str, SortBy* sort_by)
+{
+ deparseExpr(str, sort_by->node);
+ appendStringInfoChar(str, ' ');
+
+ switch (sort_by->sortby_dir)
+ {
+ case SORTBY_DEFAULT:
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ appendStringInfoString(str, "USING ");
+ deparseQualOp(str, sort_by->useOp);
+ break;
+ }
+
+ switch (sort_by->sortby_nulls)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseParamRef(StringInfo str, ParamRef* param_ref)
+{
+ if (param_ref->number == 0) {
+ appendStringInfoChar(str, '?');
+ } else {
+ appendStringInfo(str, "$%d", param_ref->number);
+ }
+}
+
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function)
+{
+ switch (sql_value_function->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ appendStringInfoString(str, "current_date");
+ break;
+ case SVFOP_CURRENT_TIME:
+ appendStringInfoString(str, "current_time");
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ appendStringInfoString(str, "current_time"); // with precision
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ appendStringInfoString(str, "current_timestamp");
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ appendStringInfoString(str, "current_timestamp"); // with precision
+ break;
+ case SVFOP_LOCALTIME:
+ appendStringInfoString(str, "localtime");
+ break;
+ case SVFOP_LOCALTIME_N:
+ appendStringInfoString(str, "localtime"); // with precision
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ appendStringInfoString(str, "localtimestamp");
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ appendStringInfoString(str, "localtimestamp"); // with precision
+ break;
+ case SVFOP_CURRENT_ROLE:
+ appendStringInfoString(str, "current_role");
+ break;
+ case SVFOP_CURRENT_USER:
+ appendStringInfoString(str, "current_user");
+ break;
+ case SVFOP_USER:
+ appendStringInfoString(str, "user");
+ break;
+ case SVFOP_SESSION_USER:
+ appendStringInfoString(str, "session_user");
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ appendStringInfoString(str, "current_catalog");
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ appendStringInfoString(str, "current_schema");
+ break;
+ }
+
+ if (sql_value_function->typmod != -1)
+ {
+ appendStringInfo(str, "(%d)", sql_value_function->typmod);
+ }
+}
+
+static void deparseWithClause(StringInfo str, WithClause *with_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "WITH ");
+ if (with_clause->recursive)
+ appendStringInfoString(str, "RECURSIVE ");
+
+ foreach(lc, with_clause->ctes) {
+ deparseCommonTableExpr(str, castNode(CommonTableExpr, lfirst(lc)));
+ if (lnext(with_clause->ctes, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
+{
+ ListCell *lc;
+ bool need_alias_parens = join_expr->alias != NULL;
+ bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
+
+ if (need_alias_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseTableRef(str, join_expr->larg);
+
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->isNatural)
+ appendStringInfoString(str, "NATURAL ");
+
+ switch (join_expr->jointype)
+ {
+ case JOIN_INNER: /* matching tuple pairs only */
+ if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
+ appendStringInfoString(str, "CROSS ");
+ break;
+ case JOIN_LEFT: /* pairs + unmatched LHS tuples */
+ appendStringInfoString(str, "LEFT ");
+ break;
+ case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
+ appendStringInfoString(str, "FULL ");
+ break;
+ case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
+ appendStringInfoString(str, "RIGHT ");
+ break;
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ case JOIN_UNIQUE_OUTER:
+ case JOIN_UNIQUE_INNER:
+ // Only used by the planner/executor, not seen in parser output
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "JOIN ");
+
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseTableRef(str, join_expr->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->quals != NULL)
+ {
+ appendStringInfoString(str, "ON ");
+ deparseExpr(str, join_expr->quals);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(join_expr->usingClause) > 0)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseNameList(str, join_expr->usingClause);
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->join_using_alias)
+ {
+ appendStringInfoString(str, "AS ");
+ appendStringInfoString(str, join_expr->join_using_alias->aliasname);
+ }
+ }
+
+ if (need_alias_parens)
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->alias != NULL)
+ deparseAlias(str, join_expr->alias);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCTESearchClause(StringInfo str, CTESearchClause *search_clause)
+{
+ appendStringInfoString(str, " SEARCH ");
+ if (search_clause->search_breadth_first)
+ appendStringInfoString(str, "BREADTH ");
+ else
+ appendStringInfoString(str, "DEPTH ");
+
+ appendStringInfoString(str, "FIRST BY ");
+
+ if (search_clause->search_col_list)
+ deparseColumnList(str, search_clause->search_col_list);
+
+ appendStringInfoString(str, " SET ");
+ appendStringInfoString(str, quote_identifier(search_clause->search_seq_column));
+}
+
+static void deparseCTECycleClause(StringInfo str, CTECycleClause *cycle_clause)
+{
+ appendStringInfoString(str, " CYCLE ");
+
+ if (cycle_clause->cycle_col_list)
+ deparseColumnList(str, cycle_clause->cycle_col_list);
+
+ appendStringInfoString(str, " SET ");
+ appendStringInfoString(str, quote_identifier(cycle_clause->cycle_mark_column));
+
+ if (cycle_clause->cycle_mark_value)
+ {
+ appendStringInfoString(str, " TO ");
+ deparseExpr(str, cycle_clause->cycle_mark_value);
+ }
+
+ if (cycle_clause->cycle_mark_default)
+ {
+ appendStringInfoString(str, " DEFAULT ");
+ deparseExpr(str, cycle_clause->cycle_mark_default);
+ }
+
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(cycle_clause->cycle_path_column));
+}
+
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
+{
+ deparseColId(str, cte->ctename);
+
+ if (list_length(cte->aliascolnames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, cte->aliascolnames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ switch (cte->ctematerialized) {
+ case CTEMaterializeDefault: /* no option specified */
+ break;
+ case CTEMaterializeAlways:
+ appendStringInfoString(str, "MATERIALIZED ");
+ break;
+ case CTEMaterializeNever:
+ appendStringInfoString(str, "NOT MATERIALIZED ");
+ break;
+ }
+
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, cte->ctequery);
+ appendStringInfoChar(str, ')');
+
+ if (cte->search_clause)
+ deparseCTESearchClause(str, cte->search_clause);
+ if (cte->cycle_clause)
+ deparseCTECycleClause(str, cte->cycle_clause);
+}
+
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
+{
+ if (range_subselect->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, range_subselect->subquery));
+ appendStringInfoChar(str, ')');
+
+ if (range_subselect->alias != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseAlias(str, range_subselect->alias);
+ }
+}
+
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (range_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ if (range_func->is_rowsfrom)
+ {
+ appendStringInfoString(str, "ROWS FROM ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->functions)
+ {
+ List *lfunc = castNode(List, lfirst(lc));
+ Assert(list_length(lfunc) == 2);
+ deparseFuncExprWindowless(str, linitial(lfunc));
+ appendStringInfoChar(str, ' ');
+ List *coldeflist = castNode(List, lsecond(lfunc));
+ if (list_length(coldeflist) > 0)
+ {
+ appendStringInfoString(str, "AS (");
+ foreach(lc2, coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc2)));
+ if (lnext(coldeflist, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ if (lnext(range_func->functions, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(list_length(linitial(range_func->functions)) == 2);
+ deparseFuncExprWindowless(str, linitial(linitial(range_func->functions)));
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (range_func->ordinality)
+ appendStringInfoString(str, "WITH ORDINALITY ");
+
+ if (range_func->alias != NULL)
+ {
+ deparseAlias(str, range_func->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(range_func->coldeflist) > 0)
+ {
+ if (range_func->alias == NULL)
+ appendStringInfoString(str, "AS ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(range_func->coldeflist, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr *array_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ARRAY[");
+ deparseExprList(str, array_expr->elements);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
+{
+ ListCell *lc;
+
+ switch (row_expr->row_format)
+ {
+ case COERCE_EXPLICIT_CALL:
+ appendStringInfoString(str, "ROW");
+ break;
+ case COERCE_SQL_SYNTAX:
+ case COERCE_EXPLICIT_CAST:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCE_IMPLICIT_CAST:
+ // No prefix
+ break;
+ }
+
+ appendStringInfoString(str, "(");
+ deparseExprList(str, row_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context)
+{
+ bool need_parens = false;
+
+ Assert(type_cast->typeName != NULL);
+
+ if (IsA(type_cast->arg, A_Expr) || context == DEPARSE_NODE_CONTEXT_FUNC_EXPR)
+ {
+ appendStringInfoString(str, "CAST(");
+ deparseExpr(str, type_cast->arg);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, type_cast->typeName);
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ if (IsA(type_cast->arg, A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, type_cast->arg);
+
+ if (list_length(type_cast->typeName->names) == 2 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
+ {
+ char *typename = strVal(lsecond(type_cast->typeName->names));
+ if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
+ {
+ appendStringInfoString(str, "char ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
+ {
+ /*
+ * Handle "bool" or "false" in the statement, which is represented as a typecast
+ * (other boolean casts should be represented as a cast, i.e. don't need special handling)
+ */
+ char *const_val = strVal(&a_const->val);
+ if (strcmp(const_val, "t") == 0)
+ {
+ appendStringInfoString(str, "true");
+ return;
+ }
+ if (strcmp(const_val, "f") == 0)
+ {
+ appendStringInfoString(str, "false");
+ return;
+ }
+ }
+ else if (strcmp(typename, "interval") == 0 && context == DEPARSE_NODE_CONTEXT_SET_STATEMENT && IsA(&a_const->val, String))
+ {
+ appendStringInfoString(str, "interval ");
+ deparseAConst(str, a_const);
+ deparseIntervalTypmods(str, type_cast->typeName);
+ return;
+ }
+ }
+
+ // Ensure negative values have wrapping parentheses
+ if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
+ {
+ need_parens = true;
+ }
+
+ if (list_length(type_cast->typeName->names) == 1 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "point") == 0 &&
+ a_const->location > type_cast->typeName->location)
+ {
+ appendStringInfoString(str, " point ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ }
+
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, type_cast->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, "::");
+ deparseTypeName(str, type_cast->typeName);
+}
+
+static void deparseTypeName(StringInfo str, TypeName *type_name)
+{
+ ListCell *lc;
+ bool skip_typmods = false;
+
+ if (type_name->setof)
+ appendStringInfoString(str, "SETOF ");
+
+ if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
+ {
+ const char *name = strVal(lsecond(type_name->names));
+ if (strcmp(name, "bpchar") == 0)
+ {
+ appendStringInfoString(str, "char");
+ }
+ else if (strcmp(name, "varchar") == 0)
+ {
+ appendStringInfoString(str, "varchar");
+ }
+ else if (strcmp(name, "numeric") == 0)
+ {
+ appendStringInfoString(str, "numeric");
+ }
+ else if (strcmp(name, "bool") == 0)
+ {
+ appendStringInfoString(str, "boolean");
+ }
+ else if (strcmp(name, "int2") == 0)
+ {
+ appendStringInfoString(str, "smallint");
+ }
+ else if (strcmp(name, "int4") == 0)
+ {
+ appendStringInfoString(str, "int");
+ }
+ else if (strcmp(name, "int8") == 0)
+ {
+ appendStringInfoString(str, "bigint");
+ }
+ else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
+ {
+ appendStringInfoString(str, "real");
+ }
+ else if (strcmp(name, "float8") == 0)
+ {
+ appendStringInfoString(str, "double precision");
+ }
+ else if (strcmp(name, "time") == 0)
+ {
+ appendStringInfoString(str, "time");
+ }
+ else if (strcmp(name, "timetz") == 0)
+ {
+ appendStringInfoString(str, "time ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "timestamp") == 0)
+ {
+ appendStringInfoString(str, "timestamp");
+ }
+ else if (strcmp(name, "timestamptz") == 0)
+ {
+ appendStringInfoString(str, "timestamp ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
+ {
+ appendStringInfoString(str, "interval");
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
+ {
+ appendStringInfoString(str, "interval");
+ deparseIntervalTypmods(str, type_name);
+
+ skip_typmods = true;
+ }
+ else
+ {
+ appendStringInfoString(str, "pg_catalog.");
+ appendStringInfoString(str, name);
+ }
+ }
+ else
+ {
+ deparseAnyName(str, type_name->names);
+ }
+
+ if (list_length(type_name->typmods) > 0 && !skip_typmods)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ if (IsA(lfirst(lc), A_Const))
+ deparseAConst(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ParamRef))
+ deparseParamRef(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ColumnRef))
+ deparseColumnRef(str, lfirst(lc));
+ else
+ Assert(false);
+
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ foreach(lc, type_name->arrayBounds)
+ {
+ appendStringInfoChar(str, '[');
+ if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
+ deparseSignedIconst(str, lfirst(lc));
+ appendStringInfoChar(str, ']');
+ }
+
+ if (type_name->pct_type)
+ appendStringInfoString(str, "%type");
+}
+
+// Handle typemods for Interval types separately
+// so that they can be applied appropriately for different contexts.
+// For example, when using `SET` a query like `INTERVAL 'x' hour TO minute`
+// the `INTERVAL` keyword is specified first.
+// In all other contexts, intervals use the `'x'::interval` style.
+static void deparseIntervalTypmods(StringInfo str, TypeName *type_name)
+{
+ const char *name = strVal(lsecond(type_name->names));
+ Assert(strcmp(name, "interval") == 0);
+ Assert(list_length(type_name->typmods) >= 1);
+ Assert(IsA(linitial(type_name->typmods), A_Const));
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
+
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
+
+ // This logic is based on intervaltypmodout in timestamp.c
+ switch (fields)
+ {
+ case INTERVAL_MASK(YEAR):
+ appendStringInfoString(str, " year");
+ break;
+ case INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " month");
+ break;
+ case INTERVAL_MASK(DAY):
+ appendStringInfoString(str, " day");
+ break;
+ case INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " hour");
+ break;
+ case INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " minute");
+ break;
+ case INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " second");
+ break;
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " year to month");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " day to hour");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " day to minute");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " day to second");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " hour to minute");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " hour to second");
+ break;
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " minute to second");
+ break;
+ case INTERVAL_FULL_RANGE:
+ // Nothing
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (list_length(type_name->typmods) == 2)
+ {
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
+ if (precision != INTERVAL_FULL_PRECISION)
+ appendStringInfo(str, "(%d)", precision);
+ }
+}
+
+static void deparseNullTest(StringInfo str, NullTest *null_test)
+{
+ // argisrow is always false in raw parser output
+ Assert(null_test->argisrow == false);
+
+ deparseExpr(str, (Node *) null_test->arg);
+ switch (null_test->nulltesttype)
+ {
+ case IS_NULL:
+ appendStringInfoString(str, " IS NULL");
+ break;
+ case IS_NOT_NULL:
+ appendStringInfoString(str, " IS NOT NULL");
+ break;
+ }
+}
+
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CASE ");
+
+ if (case_expr->arg != NULL)
+ {
+ deparseExpr(str, (Node *) case_expr->arg);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, case_expr->args)
+ {
+ deparseCaseWhen(str, castNode(CaseWhen, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (case_expr->defresult != NULL)
+ {
+ appendStringInfoString(str, "ELSE ");
+ deparseExpr(str, (Node *) case_expr->defresult);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "END");
+}
+
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when)
+{
+ appendStringInfoString(str, "WHEN ");
+ deparseExpr(str, (Node *) case_when->expr);
+ appendStringInfoString(str, " THEN ");
+ deparseExpr(str, (Node *) case_when->result);
+}
+
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection)
+{
+ ListCell *lc;
+ bool need_parens =
+ IsA(a_indirection->arg, A_Indirection) ||
+ IsA(a_indirection->arg, FuncCall) ||
+ IsA(a_indirection->arg, A_Expr) ||
+ IsA(a_indirection->arg, TypeCast) ||
+ IsA(a_indirection->arg, RowExpr) ||
+ (IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices));
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, a_indirection->arg);
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ deparseOptIndirection(str, a_indirection->indirection, 0);
+}
+
+static void deparseAIndices(StringInfo str, A_Indices *a_indices)
+{
+ appendStringInfoChar(str, '[');
+ if (a_indices->lidx != NULL)
+ deparseExpr(str, a_indices->lidx);
+ if (a_indices->is_slice)
+ appendStringInfoChar(str, ':');
+ if (a_indices->uidx != NULL)
+ deparseExpr(str, a_indices->uidx);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr)
+{
+ appendStringInfoString(str, "COALESCE(");
+ deparseExprList(str, coalesce_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr)
+{
+ switch (min_max_expr->op)
+ {
+ case IS_GREATEST:
+ appendStringInfoString(str, "GREATEST(");
+ break;
+ case IS_LEAST:
+ appendStringInfoString(str, "LEAST(");
+ break;
+ }
+ deparseExprList(str, min_max_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test)
+{
+ bool need_parens = IsA(boolean_test->arg, BoolExpr);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, (Node *) boolean_test->arg);
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ switch (boolean_test->booltesttype)
+ {
+ case IS_TRUE:
+ appendStringInfoString(str, " IS TRUE");
+ break;
+ case IS_NOT_TRUE:
+ appendStringInfoString(str, " IS NOT TRUE");
+ break;
+ case IS_FALSE:
+ appendStringInfoString(str, " IS FALSE");
+ break;
+ case IS_NOT_FALSE:
+ appendStringInfoString(str, " IS NOT FALSE");
+ break;
+ case IS_UNKNOWN:
+ appendStringInfoString(str, " IS UNKNOWN");
+ break;
+ case IS_NOT_UNKNOWN:
+ appendStringInfoString(str, " IS NOT UNKNOWN");
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
+{
+ ListCell *lc;
+
+ if (column_def->colname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(column_def->colname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->typeName != NULL)
+ {
+ deparseTypeName(str, column_def->typeName);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->raw_default != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseExpr(str, column_def->raw_default);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->fdwoptions != NULL)
+ {
+ deparseCreateGenericOptions(str, column_def->fdwoptions);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, column_def->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->collClause != NULL)
+ {
+ deparseCollateClause(str, column_def->collClause);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInsertOverride(StringInfo str, OverridingKind override)
+{
+ switch (override)
+ {
+ case OVERRIDING_NOT_SET:
+ // Do nothing
+ break;
+ case OVERRIDING_USER_VALUE:
+ appendStringInfoString(str, "OVERRIDING USER VALUE ");
+ break;
+ case OVERRIDING_SYSTEM_VALUE:
+ appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
+ break;
+ }
+}
+
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (insert_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, insert_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "INSERT INTO ");
+ deparseRangeVar(str, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(insert_stmt->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseInsertColumnList(str, insert_stmt->cols);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseInsertOverride(str, insert_stmt->override);
+
+ if (insert_stmt->selectStmt != NULL)
+ {
+ deparseSelectStmt(str, castNode(SelectStmt, insert_stmt->selectStmt));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "DEFAULT VALUES ");
+ }
+
+ if (insert_stmt->onConflictClause != NULL)
+ {
+ deparseOnConflictClause(str, insert_stmt->onConflictClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(insert_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, insert_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInferClause(StringInfo str, InferClause *infer_clause)
+{
+ ListCell *lc;
+
+ if (list_length(infer_clause->indexElems) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, infer_clause->indexElems)
+ {
+ deparseIndexElem(str, lfirst(lc));
+ if (lnext(infer_clause->indexElems, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ if (infer_clause->conname != NULL)
+ {
+ appendStringInfoString(str, "ON CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(infer_clause->conname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, infer_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ON CONFLICT ");
+
+ if (on_conflict_clause->infer != NULL)
+ {
+ deparseInferClause(str, on_conflict_clause->infer);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (on_conflict_clause->action)
+ {
+ case ONCONFLICT_NONE:
+ Assert(false);
+ break;
+ case ONCONFLICT_NOTHING:
+ appendStringInfoString(str, "DO NOTHING ");
+ break;
+ case ONCONFLICT_UPDATE:
+ appendStringInfoString(str, "DO UPDATE ");
+ break;
+ }
+
+ if (list_length(on_conflict_clause->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, on_conflict_clause->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, on_conflict_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
+{
+ ListCell* lc;
+ ListCell* lc2;
+ ListCell* lc3;
+
+ if (update_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, update_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "UPDATE ");
+ deparseRangeVar(str, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(update_stmt->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, update_stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, update_stmt->fromClause);
+ deparseWhereClause(str, update_stmt->whereClause);
+
+ if (list_length(update_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, update_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseMergeStmt(StringInfo str, MergeStmt *merge_stmt)
+{
+ if (merge_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, merge_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "MERGE INTO ");
+ deparseRangeVar(str, merge_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ deparseTableRef(str, merge_stmt->sourceRelation);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "ON ");
+ deparseExpr(str, merge_stmt->joinCondition);
+ appendStringInfoChar(str, ' ');
+
+ ListCell *lc, *lc2;
+ foreach (lc, merge_stmt->mergeWhenClauses)
+ {
+ MergeWhenClause *clause = castNode(MergeWhenClause, lfirst(lc));
+
+ appendStringInfoString(str, "WHEN ");
+
+ if (!clause->matched)
+ {
+ appendStringInfoString(str, "NOT ");
+ }
+
+ appendStringInfoString(str, "MATCHED ");
+
+ if (clause->condition)
+ {
+ appendStringInfoString(str, "AND ");
+ deparseExpr(str, clause->condition);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "THEN ");
+
+ switch (clause->commandType) {
+ case CMD_INSERT:
+ appendStringInfoString(str, "INSERT ");
+
+ if (clause->targetList) {
+ appendStringInfoChar(str, '(');
+ deparseInsertColumnList(str, clause->targetList);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseInsertOverride(str, clause->override);
+
+ if (clause->values) {
+ appendStringInfoString(str, "VALUES (");
+ deparseExprList(str, clause->values);
+ appendStringInfoString(str, ")");
+ } else {
+ appendStringInfoString(str, "DEFAULT VALUES ");
+ }
+
+ break;
+ case CMD_UPDATE:
+ appendStringInfoString(str, "UPDATE SET ");
+ deparseSetClauseList(str, clause->targetList);
+ break;
+ case CMD_DELETE:
+ appendStringInfoString(str, "DELETE");
+ break;
+ case CMD_NOTHING:
+ appendStringInfoString(str, "DO NOTHING");
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted command type in merge statement: %d", clause->commandType);
+ break;
+ }
+
+ if (lfirst(lc) != llast(merge_stmt->mergeWhenClauses))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
+{
+ if (delete_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, delete_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "DELETE FROM ");
+ deparseRangeVar(str, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (delete_stmt->usingClause != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseFromList(str, delete_stmt->usingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, delete_stmt->whereClause);
+
+ if (list_length(delete_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, delete_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause)
+{
+ ListCell *lc;
+
+ switch (locking_clause->strength)
+ {
+ case LCS_NONE:
+ /* no such clause - only used in PlanRowMark */
+ Assert(false);
+ break;
+ case LCS_FORKEYSHARE:
+ appendStringInfoString(str, "FOR KEY SHARE ");
+ break;
+ case LCS_FORSHARE:
+ appendStringInfoString(str, "FOR SHARE ");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ appendStringInfoString(str, "FOR NO KEY UPDATE ");
+ break;
+ case LCS_FORUPDATE:
+ appendStringInfoString(str, "FOR UPDATE ");
+ break;
+ }
+
+ if (list_length(locking_clause->lockedRels) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseQualifiedNameList(str, locking_clause->lockedRels);
+ }
+
+ switch (locking_clause->waitPolicy)
+ {
+ case LockWaitError:
+ appendStringInfoString(str, "NOWAIT");
+ break;
+ case LockWaitSkip:
+ appendStringInfoString(str, "SKIP LOCKED");
+ break;
+ case LockWaitBlock:
+ // Default
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default)
+{
+ appendStringInfoString(str, "DEFAULT");
+}
+
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ appendStringInfoString(str, "CREATE CAST (");
+ deparseTypeName(str, create_cast_stmt->sourcetype);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, create_cast_stmt->targettype);
+ appendStringInfoString(str, ") ");
+
+ if (create_cast_stmt->func != NULL)
+ {
+ appendStringInfoString(str, "WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_cast_stmt->func);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_cast_stmt->inout)
+ {
+ appendStringInfoString(str, "WITH INOUT ");
+ }
+ else
+ {
+ appendStringInfoString(str, "WITHOUT FUNCTION ");
+ }
+
+ switch (create_cast_stmt->context)
+ {
+ case COERCION_IMPLICIT:
+ appendStringInfoString(str, "AS IMPLICIT");
+ break;
+ case COERCION_ASSIGNMENT:
+ appendStringInfoString(str, "AS ASSIGNMENT");
+ break;
+ case COERCION_PLPGSQL:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCION_EXPLICIT:
+ // Default
+ break;
+ }
+}
+
+static void deparseCreateOpClassStmt(StringInfo str, CreateOpClassStmt *create_op_class_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE OPERATOR CLASS ");
+
+ deparseAnyName(str, create_op_class_stmt->opclassname);
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->isDefault)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, create_op_class_stmt->datatype);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_class_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->opfamilyname != NULL)
+ {
+ appendStringInfoString(str, "FAMILY ");
+ deparseAnyName(str, create_op_class_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "AS ");
+ deparseOpclassItemList(str, create_op_class_stmt->items);
+}
+
+static void deparseCreateOpFamilyStmt(StringInfo str, CreateOpFamilyStmt *create_op_family_stmt)
+{
+ appendStringInfoString(str, "CREATE OPERATOR FAMILY ");
+
+ deparseAnyName(str, create_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_family_stmt->amname));
+}
+
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item)
+{
+ ListCell *lc = NULL;
+
+ switch (create_op_class_item->itemtype)
+ {
+ case OPCLASS_ITEM_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+
+ if (create_op_class_item->name != NULL)
+ {
+ if (create_op_class_item->name->objargs != NULL)
+ deparseOperatorWithArgtypes(str, create_op_class_item->name);
+ else
+ deparseAnyOperator(str, create_op_class_item->name->objname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_op_class_item->order_family != NULL)
+ {
+ appendStringInfoString(str, "FOR ORDER BY ");
+ deparseAnyName(str, create_op_class_item->order_family);
+ }
+
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoChar(str, ')');
+ }
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoString(str, ") ");
+ }
+ if (create_op_class_item->name != NULL)
+ deparseFunctionWithArgtypes(str, create_op_class_item->name);
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_STORAGETYPE:
+ appendStringInfoString(str, "STORAGE ");
+ deparseTypeName(str, create_op_class_item->storedtype);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseTableLikeClause(StringInfo str, TableLikeClause *table_like_clause)
+{
+ appendStringInfoString(str, "LIKE ");
+ deparseRangeVar(str, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
+ appendStringInfoString(str, "INCLUDING ALL ");
+ else
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+ appendStringInfoString(str, "INCLUDING COMMENTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ appendStringInfoString(str, "INCLUDING CONSTRAINTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
+ appendStringInfoString(str, "INCLUDING DEFAULTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
+ appendStringInfoString(str, "INCLUDING IDENTITY ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED)
+ appendStringInfoString(str, "INCLUDING GENERATED ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ appendStringInfoString(str, "INCLUDING INDEXES ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
+ appendStringInfoString(str, "INCLUDING STATISTICS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ appendStringInfoString(str, "INCLUDING STORAGE ");
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt)
+{
+ ListCell *lc;
+
+ Assert(create_domain_stmt->typeName != NULL);
+
+ appendStringInfoString(str, "CREATE DOMAIN ");
+ deparseAnyName(str, create_domain_stmt->domainname);
+ appendStringInfoString(str, " AS ");
+
+ deparseTypeName(str, create_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (create_domain_stmt->collClause != NULL)
+ {
+ deparseCollateClause(str, create_domain_stmt->collClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_domain_stmt->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateExtensionStmt(StringInfo str, CreateExtensionStmt *create_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE EXTENSION ");
+
+ if (create_extension_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseColId(str, create_extension_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, create_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "schema") == 0)
+ {
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "cascade") == 0)
+ {
+ appendStringInfoString(str, "CASCADE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraint(StringInfo str, Constraint *constraint)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(constraint->conname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (constraint->contype) {
+ case CONSTR_NULL:
+ appendStringInfoString(str, "NULL ");
+ break;
+ case CONSTR_NOTNULL:
+ appendStringInfoString(str, "NOT NULL ");
+ break;
+ case CONSTR_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, constraint->raw_expr);
+ break;
+ case CONSTR_IDENTITY:
+ appendStringInfoString(str, "GENERATED ");
+ switch (constraint->generated_when)
+ {
+ case ATTRIBUTE_IDENTITY_ALWAYS:
+ appendStringInfoString(str, "ALWAYS ");
+ break;
+ case ATTRIBUTE_IDENTITY_BY_DEFAULT:
+ appendStringInfoString(str, "BY DEFAULT ");
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoString(str, "AS IDENTITY ");
+ deparseOptParenthesizedSeqOptList(str, constraint->options);
+ break;
+ case CONSTR_GENERATED:
+ Assert(constraint->generated_when == ATTRIBUTE_IDENTITY_ALWAYS);
+ appendStringInfoString(str, "GENERATED ALWAYS AS (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") STORED ");
+ break;
+ case CONSTR_CHECK:
+ appendStringInfoString(str, "CHECK (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") ");
+ break;
+ case CONSTR_PRIMARY:
+ appendStringInfoString(str, "PRIMARY KEY ");
+ break;
+ case CONSTR_UNIQUE:
+ appendStringInfoString(str, "UNIQUE ");
+ break;
+ case CONSTR_EXCLUSION:
+ appendStringInfoString(str, "EXCLUDE ");
+ if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(constraint->access_method));
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoChar(str, '(');
+ foreach(lc, constraint->exclusions)
+ {
+ List *exclusion = castNode(List, lfirst(lc));
+ Assert(list_length(exclusion) == 2);
+ deparseIndexElem(str, castNode(IndexElem, linitial(exclusion)));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyOperator(str, castNode(List, lsecond(exclusion)));
+ if (lnext(constraint->exclusions, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ if (constraint->where_clause != NULL)
+ {
+ appendStringInfoString(str, "WHERE (");
+ deparseExpr(str, constraint->where_clause);
+ appendStringInfoString(str, ") ");
+ }
+ break;
+ case CONSTR_FOREIGN:
+ if (list_length(constraint->fk_attrs) > 0)
+ appendStringInfoString(str, "FOREIGN KEY ");
+ break;
+ case CONSTR_ATTR_DEFERRABLE:
+ appendStringInfoString(str, "DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ appendStringInfoString(str, "NOT DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_DEFERRED:
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+ break;
+ case CONSTR_ATTR_IMMEDIATE:
+ appendStringInfoString(str, "INITIALLY IMMEDIATE ");
+ break;
+ }
+
+ if (list_length(constraint->keys) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->keys);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (list_length(constraint->fk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->fk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->pktable != NULL)
+ {
+ appendStringInfoString(str, "REFERENCES ");
+ deparseRangeVar(str, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ if (list_length(constraint->pk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->pk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ switch (constraint->fk_matchtype)
+ {
+ case FKCONSTR_MATCH_SIMPLE:
+ // Default
+ break;
+ case FKCONSTR_MATCH_FULL:
+ appendStringInfoString(str, "MATCH FULL ");
+ break;
+ case FKCONSTR_MATCH_PARTIAL:
+ // Not implemented in Postgres
+ Assert(false);
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_upd_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON UPDATE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON UPDATE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON UPDATE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON UPDATE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_del_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON DELETE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON DELETE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON DELETE SET ");
+
+ switch (constraint->fk_del_action) {
+ case FKCONSTR_ACTION_SETDEFAULT: appendStringInfoString(str, "DEFAULT "); break;
+ case FKCONSTR_ACTION_SETNULL: appendStringInfoString(str, "NULL "); break;
+ }
+
+ if (constraint->fk_del_set_cols) {
+ appendStringInfoString(str, "(");
+ ListCell *lc;
+ foreach (lc, constraint->fk_del_set_cols) {
+ appendStringInfoString(str, strVal(lfirst(lc)));
+ if (lfirst(lc) != llast(constraint->fk_del_set_cols))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ")");
+ }
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ if (list_length(constraint->including) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ deparseColumnList(str, constraint->including);
+ appendStringInfoString(str, ") ");
+ }
+
+ switch (constraint->contype)
+ {
+ case CONSTR_PRIMARY:
+ case CONSTR_UNIQUE:
+ case CONSTR_EXCLUSION:
+ deparseOptWith(str, constraint->options);
+ break;
+ default:
+ break;
+ }
+
+ if (constraint->indexname != NULL)
+ appendStringInfo(str, "USING INDEX %s ", quote_identifier(constraint->indexname));
+
+ if (constraint->indexspace != NULL)
+ appendStringInfo(str, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
+
+ if (constraint->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (constraint->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (constraint->is_no_inherit)
+ appendStringInfoString(str, "NO INHERIT ");
+
+ if (constraint->skip_validation)
+ appendStringInfoString(str, "NOT VALID ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReturnStmt(StringInfo str, ReturnStmt *return_stmt)
+{
+ appendStringInfoString(str, "RETURN ");
+ deparseExpr(str, return_stmt->returnval);
+}
+
+static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
+{
+ ListCell *lc;
+ bool tableFunc = false;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_function_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_function_stmt->is_procedure)
+ appendStringInfoString(str, "PROCEDURE ");
+ else
+ appendStringInfoString(str, "FUNCTION ");
+
+ deparseFuncName(str, create_function_stmt->funcname);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode != FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc) && castNode(FunctionParameter, lfirst(lnext(create_function_stmt->parameters, lc)))->mode != FUNC_PARAM_TABLE)
+ appendStringInfoString(str, ", ");
+ }
+ else
+ {
+ tableFunc = true;
+ }
+ }
+ appendStringInfoString(str, ") ");
+
+ if (tableFunc)
+ {
+ appendStringInfoString(str, "RETURNS TABLE (");
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode == FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_function_stmt->returnType != NULL)
+ {
+ appendStringInfoString(str, "RETURNS ");
+ deparseTypeName(str, create_function_stmt->returnType);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_function_stmt->options)
+ {
+ deparseCreateFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_function_stmt->sql_body)
+ {
+ /* RETURN or BEGIN ... END
+ */
+ if (IsA(create_function_stmt->sql_body, ReturnStmt))
+ {
+ deparseReturnStmt(str, castNode(ReturnStmt, create_function_stmt->sql_body));
+ }
+ else
+ {
+ appendStringInfoString(str, "BEGIN ATOMIC ");
+ if (IsA(create_function_stmt->sql_body, List), linitial((List *) create_function_stmt->sql_body) != NULL)
+ {
+ List *body_stmt_list = castNode(List, linitial((List *) create_function_stmt->sql_body));
+ foreach(lc, body_stmt_list)
+ {
+ if (IsA(lfirst(lc), ReturnStmt))
+ {
+ deparseReturnStmt(str, lfirst_node(ReturnStmt, lc));
+ appendStringInfoString(str, "; ");
+ }
+ else
+ {
+ deparseStmt(str, lfirst(lc));
+ appendStringInfoString(str, "; ");
+ }
+ }
+ }
+
+ appendStringInfoString(str, "END ");
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter)
+{
+ switch (function_parameter->mode)
+ {
+ case FUNC_PARAM_IN: /* input only */
+ appendStringInfoString(str, "IN ");
+ break;
+ case FUNC_PARAM_OUT: /* output only */
+ appendStringInfoString(str, "OUT ");
+ break;
+ case FUNC_PARAM_INOUT: /* both */
+ appendStringInfoString(str, "INOUT ");
+ break;
+ case FUNC_PARAM_VARIADIC: /* variadic (always input) */
+ appendStringInfoString(str, "VARIADIC ");
+ break;
+ case FUNC_PARAM_TABLE: /* table function output column */
+ // No special annotation, the caller is expected to correctly put
+ // this into the RETURNS part of the CREATE FUNCTION statement
+ break;
+ case FUNC_PARAM_DEFAULT:
+ // Default
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (function_parameter->name != NULL)
+ {
+ appendStringInfoString(str, function_parameter->name);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseTypeName(str, function_parameter->argType);
+ appendStringInfoChar(str, ' ');
+
+ if (function_parameter->defexpr != NULL)
+ {
+ appendStringInfoString(str, "= ");
+ deparseExpr(str, function_parameter->defexpr);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_stmt)
+{
+ appendStringInfoString(str, "CHECKPOINT");
+}
+
+static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE SCHEMA ");
+
+ if (create_schema_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (create_schema_stmt->schemaname)
+ {
+ deparseColId(str, create_schema_stmt->schemaname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->authrole != NULL)
+ {
+ appendStringInfoString(str, "AUTHORIZATION ");
+ deparseRoleSpec(str, create_schema_stmt->authrole);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->schemaElts)
+ {
+ foreach(lc, create_schema_stmt->schemaElts)
+ {
+ deparseSchemaStmt(str, lfirst(lc));
+ if (lnext(create_schema_stmt->schemaElts, lc))
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleSetStmt(StringInfo str, AlterRoleSetStmt *alter_role_set_stmt)
+{
+ appendStringInfoString(str, "ALTER ROLE ");
+
+ if (alter_role_set_stmt->role == NULL)
+ appendStringInfoString(str, "ALL");
+ else
+ deparseRoleSpec(str, alter_role_set_stmt->role);
+
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_set_stmt->database != NULL)
+ {
+ appendStringInfoString(str, "IN DATABASE ");
+ appendStringInfoString(str, quote_identifier(alter_role_set_stmt->database));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseVariableSetStmt(str, alter_role_set_stmt->setstmt);
+}
+
+static void deparseCreateConversionStmt(StringInfo str, CreateConversionStmt *create_conversion_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_conversion_stmt->def)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, create_conversion_stmt->conversion_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "FOR ");
+ deparseStringLiteral(str, create_conversion_stmt->for_encoding_name);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, create_conversion_stmt->to_encoding_name);
+
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, create_conversion_stmt->func_name);
+}
+
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
+{
+ switch (role_spec->roletype)
+ {
+ case ROLESPEC_CSTRING:
+ Assert(role_spec->rolename != NULL);
+ appendStringInfoString(str, quote_identifier(role_spec->rolename));
+ break;
+ case ROLESPEC_CURRENT_ROLE:
+ appendStringInfoString(str, "CURRENT_ROLE");
+ break;
+ case ROLESPEC_CURRENT_USER:
+ appendStringInfoString(str, "CURRENT_USER");
+ break;
+ case ROLESPEC_SESSION_USER:
+ appendStringInfoString(str, "SESSION_USER");
+ break;
+ case ROLESPEC_PUBLIC:
+ appendStringInfoString(str, "public");
+ break;
+ }
+}
+
+// "part_elem" in gram.y
+static void deparsePartitionElem(StringInfo str, PartitionElem *partition_elem)
+{
+ ListCell *lc;
+
+ if (partition_elem->name != NULL)
+ {
+ deparseColId(str, partition_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (partition_elem->expr != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, partition_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptCollate(str, partition_elem->collation);
+ deparseAnyName(str, partition_elem->opclass);
+
+ removeTrailingSpace(str);
+}
+
+static void deparsePartitionSpec(StringInfo str, PartitionSpec *partition_spec)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "PARTITION BY ");
+ appendStringInfoString(str, partition_spec->strategy);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, partition_spec->partParams)
+ {
+ deparsePartitionElem(str, castNode(PartitionElem, lfirst(lc)));
+ if (lnext(partition_spec->partParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparsePartitionBoundSpec(StringInfo str, PartitionBoundSpec *partition_bound_spec)
+{
+ ListCell *lc;
+
+ if (partition_bound_spec->is_default)
+ {
+ appendStringInfoString(str, "DEFAULT");
+ return;
+ }
+
+ appendStringInfoString(str, "FOR VALUES ");
+
+ switch (partition_bound_spec->strategy)
+ {
+ case PARTITION_STRATEGY_HASH:
+ appendStringInfo(str, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
+ break;
+ case PARTITION_STRATEGY_LIST:
+ appendStringInfoString(str, "IN (");
+ deparseExprList(str, partition_bound_spec->listdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ appendStringInfoString(str, "FROM (");
+ deparseExprList(str, partition_bound_spec->lowerdatums);
+ appendStringInfoString(str, ") TO (");
+ deparseExprList(str, partition_bound_spec->upperdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
+{
+ deparseRangeVar(str, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (partition_cmd->bound != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparsePartitionBoundSpec(str, partition_cmd->bound);
+ }
+ if (partition_cmd->concurrent)
+ appendStringInfoString(str, " CONCURRENTLY ");
+}
+
+// "TableElement" in gram.y
+static void deparseTableElement(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnDef:
+ deparseColumnDef(str, castNode(ColumnDef, node));
+ break;
+ case T_TableLikeClause:
+ deparseTableLikeClause(str, castNode(TableLikeClause, node));
+ break;
+ case T_Constraint:
+ deparseConstraint(str, castNode(Constraint, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseCreateStmt(StringInfo str, CreateStmt *create_stmt, bool is_foreign_table)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (is_foreign_table)
+ appendStringInfoString(str, "FOREIGN ");
+
+ deparseOptTemp(str, create_stmt->relation->relpersistence);
+
+ appendStringInfoString(str, "TABLE ");
+
+ if (create_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_stmt->ofTypename != NULL)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseTypeName(str, create_stmt->ofTypename);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ Assert(list_length(create_stmt->inhRelations) == 1);
+ appendStringInfoString(str, "PARTITION OF ");
+ deparseRangeVar(str, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(create_stmt->tableElts) > 0)
+ {
+ // In raw parse output tableElts contains both columns and constraints
+ // (and the constraints field is NIL)
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_stmt->tableElts)
+ {
+ deparseTableElement(str, lfirst(lc));
+ if (lnext(create_stmt->tableElts, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
+ {
+ appendStringInfoString(str, "() ");
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ deparsePartitionBoundSpec(str, create_stmt->partbound);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ deparseOptInherit(str, create_stmt->inhRelations);
+ }
+
+ if (create_stmt->partspec != NULL)
+ {
+ deparsePartitionSpec(str, create_stmt->partspec);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_stmt->accessMethod));
+ }
+
+ deparseOptWith(str, create_stmt->options);
+
+ switch (create_stmt->oncommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No ON COMMIT clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (create_stmt->tablespacename != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(create_stmt->tablespacename));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFdwStmt(StringInfo str, CreateFdwStmt *create_fdw_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, create_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseCreateGenericOptions(str, create_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFdwStmt(StringInfo str, AlterFdwStmt *alter_fdw_stmt)
+{
+ appendStringInfoString(str, "ALTER FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(alter_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, alter_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_fdw_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateForeignServerStmt(StringInfo str, CreateForeignServerStmt *create_foreign_server_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SERVER ");
+ if (create_foreign_server_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (create_foreign_server_stmt->servertype != NULL)
+ {
+ appendStringInfoString(str, "TYPE ");
+ deparseStringLiteral(str, create_foreign_server_stmt->servertype);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_foreign_server_stmt->version != NULL)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseStringLiteral(str, create_foreign_server_stmt->version);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterForeignServerStmt(StringInfo str, AlterForeignServerStmt *alter_foreign_server_stmt)
+{
+ appendStringInfoString(str, "ALTER SERVER ");
+
+ appendStringInfoString(str, quote_identifier(alter_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_foreign_server_stmt->has_version)
+ {
+ appendStringInfoString(str, "VERSION ");
+ if (alter_foreign_server_stmt->version != NULL)
+ deparseStringLiteral(str, alter_foreign_server_stmt->version);
+ else
+ appendStringInfoString(str, "NULL");
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_foreign_server_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateUserMappingStmt(StringInfo str, CreateUserMappingStmt *create_user_mapping_stmt)
+{
+ appendStringInfoString(str, "CREATE USER MAPPING ");
+ if (create_user_mapping_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, create_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(create_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreatedbStmt(StringInfo str, CreatedbStmt *createdb_stmt)
+{
+ appendStringInfoString(str, "CREATE DATABASE ");
+ deparseColId(str, createdb_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, createdb_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterUserMappingStmt(StringInfo str, AlterUserMappingStmt *alter_user_mapping_stmt)
+{
+ appendStringInfoString(str, "ALTER USER MAPPING FOR ");
+ deparseRoleSpec(str, alter_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(alter_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseAlterGenericOptions(str, alter_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropUserMappingStmt(StringInfo str, DropUserMappingStmt *drop_user_mapping_stmt)
+{
+ appendStringInfoString(str, "DROP USER MAPPING ");
+
+ if (drop_user_mapping_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, drop_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(drop_user_mapping_stmt->servername));
+}
+
+static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "SECURITY LABEL ");
+
+ if (sec_label_stmt->provider != NULL)
+ {
+ appendStringInfoString(str, "FOR ");
+ appendStringInfoString(str, quote_identifier(sec_label_stmt->provider));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ switch (sec_label_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseValue(str, (union ValUnion *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ default:
+ // Not supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (sec_label_stmt->label != NULL)
+ deparseStringLiteral(str, sec_label_stmt->label);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateForeignTableStmt(StringInfo str, CreateForeignTableStmt *create_foreign_table_stmt)
+{
+ ListCell *lc;
+
+ deparseCreateStmt(str, &create_foreign_table_stmt->base, true);
+
+ appendStringInfoString(str, " SERVER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_table_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_foreign_table_stmt->options) > 0)
+ deparseAlterGenericOptions(str, create_foreign_table_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseImportForeignSchemaStmt(StringInfo str, ImportForeignSchemaStmt *import_foreign_schema_stmt)
+{
+ appendStringInfoString(str, "IMPORT FOREIGN SCHEMA ");
+
+ appendStringInfoString(str, import_foreign_schema_stmt->remote_schema);
+ appendStringInfoChar(str, ' ');
+
+ switch (import_foreign_schema_stmt->list_type)
+ {
+ case FDW_IMPORT_SCHEMA_ALL:
+ // Default
+ break;
+ case FDW_IMPORT_SCHEMA_LIMIT_TO:
+ appendStringInfoString(str, "LIMIT TO (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ case FDW_IMPORT_SCHEMA_EXCEPT:
+ appendStringInfoString(str, "EXCEPT (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ }
+
+ appendStringInfoString(str, "FROM SERVER ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->server_name));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "INTO ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->local_schema));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, import_foreign_schema_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_table_as_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
+
+ switch (create_table_as_stmt->objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ if (create_table_as_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseIntoClause(str, create_table_as_stmt->into);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ if (IsA(create_table_as_stmt->query, ExecuteStmt))
+ deparseExecuteStmt(str, castNode(ExecuteStmt, create_table_as_stmt->query));
+ else
+ deparseSelectStmt(str, castNode(SelectStmt, create_table_as_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_as_stmt->into->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (view_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ deparseOptTemp(str, view_stmt->view->relpersistence);
+
+ appendStringInfoString(str, "VIEW ");
+ deparseRangeVar(str, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(view_stmt->aliases) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, view_stmt->aliases);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, view_stmt->options);
+
+ appendStringInfoString(str, "AS ");
+ deparseSelectStmt(str, castNode(SelectStmt, view_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ switch (view_stmt->withCheckOption)
+ {
+ case NO_CHECK_OPTION:
+ // Default
+ break;
+ case LOCAL_CHECK_OPTION:
+ appendStringInfoString(str, "WITH LOCAL CHECK OPTION ");
+ break;
+ case CASCADED_CHECK_OPTION:
+ appendStringInfoString(str, "WITH CHECK OPTION ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "DROP ");
+
+ switch (drop_stmt->removeType)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ default:
+ // Other object types are not supported here in the parser
+ Assert(false);
+ }
+
+ if (drop_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (drop_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (drop_stmt->removeType)
+ {
+ // drop_type_any_name
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ deparseAnyNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name_on_any_name
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseColId(str, strVal(llast(l)));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_CAST:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TRANSFORM:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_LANGUAGE:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_AGGREGATE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPERATOR:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseOptDropBehavior(str, drop_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set)
+{
+ switch(grouping_set->kind)
+ {
+ case GROUPING_SET_EMPTY:
+ appendStringInfoString(str, "()");
+ break;
+ case GROUPING_SET_SIMPLE:
+ // Not present in raw parse trees
+ Assert(false);
+ break;
+ case GROUPING_SET_ROLLUP:
+ appendStringInfoString(str, "ROLLUP (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_CUBE:
+ appendStringInfoString(str, "CUBE (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_SETS:
+ appendStringInfoString(str, "GROUPING SETS (");
+ deparseGroupByList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ }
+}
+
+static void deparseDropTableSpaceStmt(StringInfo str, DropTableSpaceStmt *drop_table_space_stmt)
+{
+ appendStringInfoString(str, "DROP TABLESPACE ");
+
+ if (drop_table_space_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_table_space_stmt->tablespacename);
+}
+
+static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt *alter_object_depends_stmt)
+{
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_depends_stmt->objectType)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ deparseColId(str, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ // No other object types supported here
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (alter_object_depends_stmt->remove)
+ appendStringInfoString(str, "NO ");
+
+ appendStringInfo(str, "DEPENDS ON EXTENSION %s", alter_object_depends_stmt->extname->sval);
+}
+
+static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
+{
+ List *l = NULL;
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_schema_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ appendStringInfoString(str, quote_identifier(strVal(alter_object_schema_stmt->object)));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " SET SCHEMA ");
+ appendStringInfoString(str, quote_identifier(alter_object_schema_stmt->newschema));
+}
+
+static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+ const char *options = NULL;
+ bool trailing_missing_ok = false;
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AddColumn: /* add column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ADD ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ADD COLUMN ");
+ break;
+ case AT_AddColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_ColumnDefault: /* alter column default */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ if (alter_table_cmd->def != NULL)
+ options = "SET DEFAULT";
+ else
+ options = "DROP DEFAULT";
+ break;
+ case AT_CookedColumnDefault: /* add a pre-cooked column default */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropNotNull: /* alter column drop not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP NOT NULL";
+ break;
+ case AT_SetNotNull: /* alter column set not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET NOT NULL";
+ break;
+ case AT_DropExpression: /* alter column drop expression */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP EXPRESSION";
+ trailing_missing_ok = true;
+ break;
+ case AT_CheckNotNull: /* check column is already marked not null */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_SetStatistics: /* alter column set statistics */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STATISTICS";
+ break;
+ case AT_SetOptions: /* alter column set ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET";
+ break;
+ case AT_ResetOptions: /* alter column reset ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "RESET";
+ break;
+ case AT_SetStorage: /* alter column set storage */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STORAGE";
+ break;
+ case AT_SetCompression: /* alter column set compression */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET COMPRESSION";
+ break;
+ case AT_DropColumn: /* drop column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "DROP ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "DROP ");
+ break;
+ case AT_DropColumnRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndex: /* add index */
+ appendStringInfoString(str, "ADD INDEX ");
+ break;
+ case AT_ReAddIndex: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddConstraint: /* add constraint */
+ appendStringInfoString(str, "ADD ");
+ break;
+ case AT_AddConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterConstraint: /* alter constraint */
+ appendStringInfoString(str, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
+ break;
+ case AT_ValidateConstraint: /* validate constraint */
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ break;
+ case AT_ValidateConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddIndexConstraint: /* add constraint using existing index */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropConstraint: /* drop constraint */
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ break;
+ case AT_DropConstraintRecurse: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddComment: /* internal to commands/tablecmds.c */
+ case AT_ReAddStatistics: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterColumnType: /* alter column type */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ALTER ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "TYPE";
+ break;
+ case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ // Handled via special case in def handling
+ break;
+ case AT_ChangeOwner: /* change owner */
+ appendStringInfoString(str, "OWNER TO ");
+ deparseRoleSpec(str, alter_table_cmd->newowner);
+ break;
+ case AT_ClusterOn: /* CLUSTER ON */
+ appendStringInfoString(str, "CLUSTER ON ");
+ break;
+ case AT_DropCluster: /* SET WITHOUT CLUSTER */
+ appendStringInfoString(str, "SET WITHOUT CLUSTER ");
+ break;
+ case AT_SetLogged: /* SET LOGGED */
+ appendStringInfoString(str, "SET LOGGED ");
+ break;
+ case AT_SetUnLogged: /* SET UNLOGGED */
+ appendStringInfoString(str, "SET UNLOGGED ");
+ break;
+ case AT_DropOids: /* SET WITHOUT OIDS */
+ appendStringInfoString(str, "SET WITHOUT OIDS ");
+ break;
+ case AT_SetTableSpace: /* SET TABLESPACE */
+ appendStringInfoString(str, "SET TABLESPACE ");
+ break;
+ case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
+ appendStringInfoString(str, "SET ");
+ break;
+ case AT_SetAccessMethod:
+ appendStringInfo(str, "SET ACCESS METHOD ");
+ break;
+ case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
+ appendStringInfoString(str, "RESET ");
+ break;
+ case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_EnableTrig: /* ENABLE TRIGGER name */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
+ appendStringInfoString(str, "ENABLE ALWAYS TRIGGER ");
+ break;
+ case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
+ appendStringInfoString(str, "ENABLE REPLICA TRIGGER ");
+ break;
+ case AT_DisableTrig: /* DISABLE TRIGGER name */
+ appendStringInfoString(str, "DISABLE TRIGGER ");
+ break;
+ case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
+ appendStringInfoString(str, "ENABLE TRIGGER ALL ");
+ break;
+ case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
+ appendStringInfoString(str, "DISABLE TRIGGER ALL ");
+ break;
+ case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
+ appendStringInfoString(str, "ENABLE TRIGGER USER ");
+ break;
+ case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
+ appendStringInfoString(str, "DISABLE TRIGGER USER ");
+ break;
+ case AT_EnableRule: /* ENABLE RULE name */
+ appendStringInfoString(str, "ENABLE RULE ");
+ break;
+ case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
+ appendStringInfoString(str, "ENABLE ALWAYS RULE ");
+ break;
+ case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
+ appendStringInfoString(str, "ENABLE REPLICA RULE ");
+ break;
+ case AT_DisableRule: /* DISABLE RULE name */
+ appendStringInfoString(str, "DISABLE RULE ");
+ break;
+ case AT_AddInherit: /* INHERIT parent */
+ appendStringInfoString(str, "INHERIT ");
+ break;
+ case AT_DropInherit: /* NO INHERIT parent */
+ appendStringInfoString(str, "NO INHERIT ");
+ break;
+ case AT_AddOf: /* OF */
+ appendStringInfoString(str, "OF ");
+ break;
+ case AT_DropOf: /* NOT OF */
+ appendStringInfoString(str, "NOT OF ");
+ break;
+ case AT_ReplicaIdentity: /* REPLICA IDENTITY */
+ appendStringInfoString(str, "REPLICA IDENTITY ");
+ break;
+ case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
+ appendStringInfoString(str, "ENABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
+ appendStringInfoString(str, "DISABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
+ appendStringInfoString(str, "FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
+ appendStringInfoString(str, "NO FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_GenericOptions: /* OPTIONS (...) */
+ // Handled in def field handling
+ break;
+ case AT_AttachPartition: /* ATTACH PARTITION */
+ appendStringInfoString(str, "ATTACH PARTITION ");
+ break;
+ case AT_DetachPartition: /* DETACH PARTITION */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_DetachPartitionFinalize: /* DETACH PARTITION FINALIZE */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_AddIdentity: /* ADD IDENTITY */
+ appendStringInfoString(str, "ALTER ");
+ options = "ADD";
+ // Other details are output via the constraint node (in def field)
+ break;
+ case AT_SetIdentity: /* SET identity column options */
+ appendStringInfoString(str, "ALTER ");
+ break;
+ case AT_DropIdentity: /* DROP IDENTITY */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP IDENTITY";
+ trailing_missing_ok = true;
+ break;
+ }
+
+ if (alter_table_cmd->missing_ok && !trailing_missing_ok)
+ {
+ if (alter_table_cmd->subtype == AT_AddColumn)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ else
+ appendStringInfoString(str, "IF EXISTS ");
+ }
+
+ if (alter_table_cmd->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(alter_table_cmd->name));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->num > 0)
+ appendStringInfo(str, "%d ", alter_table_cmd->num);
+
+ if (options != NULL)
+ {
+ appendStringInfoString(str, options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->missing_ok && trailing_missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_DetachPartitionFinalize:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoString(str, "FINALIZE ");
+ break;
+ case AT_AddColumn:
+ case AT_AlterColumnType:
+ deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ColumnDefault:
+ if (alter_table_cmd->def != NULL)
+ {
+ deparseExpr(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case AT_SetStatistics:
+ deparseSignedIconst(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetOptions:
+ case AT_ResetOptions:
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+ deparseRelOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetStorage:
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetCompression:
+ if (strcmp(strVal(alter_table_cmd->def), "default") == 0)
+ appendStringInfoString(str, "DEFAULT");
+ else
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddIdentity:
+ case AT_AddConstraint:
+ case AT_AlterConstraint:
+ deparseConstraint(str, castNode(Constraint, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetIdentity:
+ deparseAlterIdentityColumnOptionList(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AlterColumnGenericOptions:
+ case AT_GenericOptions:
+ deparseAlterGenericOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddInherit:
+ case AT_DropInherit:
+ deparseRangeVar(str, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddOf:
+ deparseTypeName(str, castNode(TypeName, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ReplicaIdentity:
+ deparseReplicaIdentityStmt(str, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(alter_table_cmd->def == NULL);
+ break;
+ }
+
+ deparseOptDropBehavior(str, alter_table_cmd->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static DeparseNodeContext deparseAlterTableObjType(StringInfo str, ObjectType type)
+{
+ switch (type)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ return DEPARSE_NODE_CONTEXT_ALTER_TYPE;
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ return DEPARSE_NODE_CONTEXT_NONE;
+}
+
+static void deparseAlterTableMoveAllStmt(StringInfo str, AlterTableMoveAllStmt *move_all_stmt)
+{
+ appendStringInfoString(str, "ALTER ");
+ deparseAlterTableObjType(str, move_all_stmt->objtype);
+
+ appendStringInfoString(str, "ALL IN TABLESPACE ");
+ appendStringInfoString(str, move_all_stmt->orig_tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (move_all_stmt->roles)
+ {
+ appendStringInfoString(str, "OWNED BY ");
+ deparseRoleList(str, move_all_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "SET TABLESPACE ");
+ appendStringInfoString(str, move_all_stmt->new_tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (move_all_stmt->nowait)
+ {
+ appendStringInfoString(str, "NOWAIT");
+ }
+}
+
+static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+ DeparseNodeContext context = deparseAlterTableObjType(str, alter_table_stmt->objtype);
+
+ if (alter_table_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_table_stmt->relation, context);
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, alter_table_stmt->cmds)
+ {
+ deparseAlterTableCmd(str, castNode(AlterTableCmd, lfirst(lc)), context);
+ if (lnext(alter_table_stmt->cmds, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterTableSpaceOptionsStmt(StringInfo str, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
+{
+ appendStringInfoString(str, "ALTER TABLESPACE ");
+ deparseColId(str, alter_table_space_options_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_table_space_options_stmt->isReset)
+ appendStringInfoString(str, "RESET ");
+ else
+ appendStringInfoString(str, "SET ");
+
+ deparseRelOptions(str, alter_table_space_options_stmt->options);
+}
+
+static void deparseAlterDomainStmt(StringInfo str, AlterDomainStmt *alter_domain_stmt)
+{
+ appendStringInfoString(str, "ALTER DOMAIN ");
+ deparseAnyName(str, alter_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_domain_stmt->subtype)
+ {
+ case 'T':
+ if (alter_domain_stmt->def != NULL)
+ {
+ appendStringInfoString(str, "SET DEFAULT ");
+ deparseExpr(str, alter_domain_stmt->def);
+ }
+ else
+ {
+ appendStringInfoString(str, "DROP DEFAULT");
+ }
+ break;
+ case 'N':
+ appendStringInfoString(str, "DROP NOT NULL");
+ break;
+ case 'O':
+ appendStringInfoString(str, "SET NOT NULL");
+ break;
+ case 'C':
+ appendStringInfoString(str, "ADD ");
+ deparseConstraint(str, castNode(Constraint, alter_domain_stmt->def));
+ break;
+ case 'X':
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ if (alter_domain_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ if (alter_domain_stmt->behavior == DROP_CASCADE)
+ appendStringInfoString(str, " CASCADE");
+ break;
+ case 'V':
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ break;
+ default:
+ // No other subtypes supported by the parser
+ Assert(false);
+ }
+}
+
+static void deparseRenameStmt(StringInfo str, RenameStmt *rename_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_COLUMN:
+ switch (rename_stmt->relationType)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ Assert(false);
+ }
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_ATTRIBUTE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (rename_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, rename_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseColId(str, strVal(rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLUMN:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME COLUMN ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(strVal(rename_stmt->object)));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_DOMAIN:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TYPE:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_ATTRIBUTE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
+ appendStringInfoString(str, " RENAME ATTRIBUTE ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->newname));
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDropBehavior(str, rename_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_stmt)
+{
+ ListCell *lc;
+ switch (transaction_stmt->kind)
+ {
+ case TRANS_STMT_BEGIN:
+ appendStringInfoString(str, "BEGIN ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_START:
+ appendStringInfoString(str, "START TRANSACTION ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_COMMIT:
+ appendStringInfoString(str, "COMMIT ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_ROLLBACK:
+ appendStringInfoString(str, "ROLLBACK ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_SAVEPOINT:
+ appendStringInfoString(str, "SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_RELEASE:
+ appendStringInfoString(str, "RELEASE ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_ROLLBACK_TO:
+ appendStringInfoString(str, "ROLLBACK ");
+ appendStringInfoString(str, "TO SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_PREPARE:
+ appendStringInfoString(str, "PREPARE TRANSACTION ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_COMMIT_PREPARED:
+ appendStringInfoString(str, "COMMIT PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_ROLLBACK_PREPARED:
+ appendStringInfoString(str, "ROLLBACK PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+// Determine if we hit SET TIME ZONE INTERVAL, that has special syntax not
+// supported for other SET statements
+static bool isSetTimeZoneInterval(VariableSetStmt* stmt)
+{
+ if (!(strcmp(stmt->name, "timezone") == 0 &&
+ list_length(stmt->args) == 1 &&
+ IsA(linitial(stmt->args), TypeCast)))
+ return false;
+
+ TypeName* typeName = castNode(TypeCast, linitial(stmt->args))->typeName;
+
+ return (list_length(typeName->names) == 2 &&
+ strcmp(strVal(linitial(typeName->names)), "pg_catalog") == 0 &&
+ strcmp(strVal(llast(typeName->names)), "interval") == 0);
+}
+
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
+{
+ ListCell *lc;
+
+ switch (variable_set_stmt->kind)
+ {
+ case VAR_SET_VALUE: /* SET var = value */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ if (isSetTimeZoneInterval(variable_set_stmt))
+ {
+ appendStringInfoString(str, "TIME ZONE ");
+ deparseVarList(str, variable_set_stmt->args);
+ }
+ else
+ {
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO ");
+ deparseVarList(str, variable_set_stmt->args);
+ }
+ break;
+ case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO DEFAULT");
+ break;
+ case VAR_SET_CURRENT: /* SET var FROM CURRENT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " FROM CURRENT");
+ break;
+ case VAR_SET_MULTI: /* special case for SET TRANSACTION ... */
+ Assert(variable_set_stmt->name != NULL);
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
+ {
+ appendStringInfoString(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION SNAPSHOT ");
+ deparseStringLiteral(str, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case VAR_RESET: /* RESET var */
+ appendStringInfoString(str, "RESET ");
+ deparseVarName(str, variable_set_stmt->name);
+ break;
+ case VAR_RESET_ALL: /* RESET ALL */
+ appendStringInfoString(str, "RESET ALL");
+ break;
+ }
+}
+
+static void deparseDropdbStmt(StringInfo str, DropdbStmt *dropdb_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "DROP DATABASE ");
+ if (dropdb_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, quote_identifier(dropdb_stmt->dbname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(dropdb_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, dropdb_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "force") == 0)
+ appendStringInfoString(str, "FORCE");
+ else
+ Assert(false); // Currently there are other supported values
+
+ if (lnext(dropdb_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ if (vacuum_stmt->is_vacuumcmd)
+ appendStringInfoString(str, "VACUUM ");
+ else
+ appendStringInfoString(str, "ANALYZE ");
+
+ deparseUtilityOptionList(str, vacuum_stmt->options);
+
+ foreach(lc, vacuum_stmt->rels)
+ {
+ Assert(IsA(lfirst(lc), VacuumRelation));
+ VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
+
+ deparseRangeVar(str, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(rel->va_cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc2, rel->va_cols)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc2))));
+ if (lnext(rel->va_cols, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ if (lnext(vacuum_stmt->rels, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLoadStmt(StringInfo str, LoadStmt *load_stmt)
+{
+ appendStringInfoString(str, "LOAD ");
+ deparseStringLiteral(str, load_stmt->filename);
+}
+
+static void deparseLockStmt(StringInfo str, LockStmt *lock_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "LOCK TABLE ");
+
+ deparseRelationExprList(str, lock_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (lock_stmt->mode != AccessExclusiveLock)
+ {
+ appendStringInfoString(str, "IN ");
+ switch (lock_stmt->mode)
+ {
+ case AccessShareLock:
+ appendStringInfoString(str, "ACCESS SHARE ");
+ break;
+ case RowShareLock:
+ appendStringInfoString(str, "ROW SHARE ");
+ break;
+ case RowExclusiveLock:
+ appendStringInfoString(str, "ROW EXCLUSIVE ");
+ break;
+ case ShareUpdateExclusiveLock:
+ appendStringInfoString(str, "SHARE UPDATE EXCLUSIVE ");
+ break;
+ case ShareLock:
+ appendStringInfoString(str, "SHARE ");
+ break;
+ case ShareRowExclusiveLock:
+ appendStringInfoString(str, "SHARE ROW EXCLUSIVE ");
+ break;
+ case ExclusiveLock:
+ appendStringInfoString(str, "EXCLUSIVE ");
+ break;
+ case AccessExclusiveLock:
+ appendStringInfoString(str, "ACCESS EXCLUSIVE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+ appendStringInfoString(str, "MODE ");
+ }
+
+ if (lock_stmt->nowait)
+ appendStringInfoString(str, "NOWAIT ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraintsSetStmt(StringInfo str, ConstraintsSetStmt *constraints_set_stmt)
+{
+ appendStringInfoString(str, "SET CONSTRAINTS ");
+
+ if (list_length(constraints_set_stmt->constraints) > 0)
+ {
+ deparseQualifiedNameList(str, constraints_set_stmt->constraints);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ if (constraints_set_stmt->deferred)
+ appendStringInfoString(str, "DEFERRED");
+ else
+ appendStringInfoString(str, "IMMEDIATE");
+}
+
+static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ appendStringInfoString(str, "EXPLAIN ");
+
+ deparseUtilityOptionList(str, explain_stmt->options);
+
+ deparseExplainableStmt(str, explain_stmt->query);
+}
+
+static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "COPY ");
+
+ if (copy_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(copy_stmt->attlist) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, copy_stmt->attlist);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (copy_stmt->query != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, copy_stmt->query);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "FROM ");
+ else
+ appendStringInfoString(str, "TO ");
+
+ if (copy_stmt->is_program)
+ appendStringInfoString(str, "PROGRAM ");
+
+ if (copy_stmt->filename != NULL)
+ {
+ deparseStringLiteral(str, copy_stmt->filename);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "STDIN ");
+ else
+ appendStringInfoString(str, "STDOUT ");
+ }
+
+ if (list_length(copy_stmt->options) > 0)
+ {
+ // In some cases, equivalent expressions may have slightly different parse trees for `COPY`
+ // statements. For example the following two statements result in different (but equivalent) parse
+ // trees:
+ //
+ // - COPY foo FROM STDIN CSV FREEZE
+ // - COPY foo FROM STDIN WITH (FORMAT CSV, FREEZE)
+ //
+ // In order to make sure we deparse to the "correct" version, we always try to deparse to the older
+ // compact syntax first.
+ //
+ // The old syntax can be seen here in the Postgres 8.4 Reference:
+ // https://www.postgresql.org/docs/8.4/sql-copy.html
+
+ bool old_fmt = true;
+
+ // Loop over the options to see if any require the new `WITH (...)` syntax.
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
+ {}
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {}
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
+ {}
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
+ {}
+ else
+ {
+ old_fmt = false;
+ break;
+ }
+ }
+
+ // Branch to differing output modes, depending on if we can use the old syntax.
+ if (old_fmt) {
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
+ {
+ appendStringInfoString(str, "FREEZE ");
+ }
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {
+ appendStringInfoString(str, "HEADER ");
+ }
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
+ {
+ appendStringInfoString(str, "CSV ");
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
+ {
+ appendStringInfoString(str, "FORCE QUOTE ");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ // This isn't reachable, the conditions here are exactly the same as the first loop above.
+ Assert(false);
+ }
+ }
+ } else {
+ appendStringInfoString(str, "WITH (");
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "format") == 0)
+ {
+ appendStringInfoString(str, "FORMAT ");
+
+ char *format = strVal(def_elem->arg);
+ if (strcmp(format, "binary") == 0)
+ appendStringInfoString(str, "BINARY");
+ else if (strcmp(format, "csv") == 0)
+ appendStringInfoString(str, "CSV");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "freeze") == 0)
+ {
+ appendStringInfoString(str, "FREEZE");
+ deparseOptBoolean(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
+ {
+ appendStringInfoString(str, "DELIMITER ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "null") == 0)
+ {
+ appendStringInfoString(str, "NULL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "header") == 0)
+ {
+ appendStringInfoString(str, "HEADER");
+ deparseOptBoolean(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "quote") == 0)
+ {
+ appendStringInfoString(str, "QUOTE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "escape") == 0)
+ {
+ appendStringInfoString(str, "ESCAPE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
+ {
+ appendStringInfoString(str, "FORCE_QUOTE ");
+ if (IsA(def_elem->arg, A_Star))
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NOT_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "force_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "encoding") == 0)
+ {
+ appendStringInfoString(str, "ENCODING ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL)
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ {
+ // Nothing
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ {
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAStar(str, castNode(A_Star, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoChar(str, '(');
+ foreach(lc2, l)
+ {
+ deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ }
+
+ if (lnext(copy_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ deparseWhereClause(str, copy_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDoStmt(StringInfo str, DoStmt *do_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DO ");
+
+ foreach (lc, do_stmt->args)
+ {
+ DefElem *defel = castNode(DefElem, lfirst(lc));
+ if (strcmp(defel->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(defel->arg)));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defel->defname, "as") == 0)
+ {
+ char *strval = strVal(defel->arg);
+ const char *delim = "$$";
+ if (strstr(strval, "$$") != NULL)
+ delim = "$outer$";
+ appendStringInfoString(str, delim);
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, delim);
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDiscardStmt(StringInfo str, DiscardStmt *discard_stmt)
+{
+ appendStringInfoString(str, "DISCARD ");
+ switch (discard_stmt->target)
+ {
+ case DISCARD_ALL:
+ appendStringInfoString(str, "ALL");
+ break;
+ case DISCARD_PLANS:
+ appendStringInfoString(str, "PLANS");
+ break;
+ case DISCARD_SEQUENCES:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case DISCARD_TEMP:
+ appendStringInfoString(str, "TEMP");
+ break;
+ }
+}
+
+static void deparseDefineStmt(StringInfo str, DefineStmt *define_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (define_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ default:
+ // This shouldn't happen
+ Assert(false);
+ break;
+ }
+
+ if (define_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseFuncName(str, define_stmt->defnames);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAnyOperator(str, define_stmt->defnames);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_COLLATION:
+ deparseAnyName(str, define_stmt->defnames);
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
+ {
+ deparseAggrArgs(str, define_stmt->args);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (define_stmt->kind == OBJECT_COLLATION &&
+ list_length(define_stmt->definition) == 1 &&
+ strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
+ }
+ else if (list_length(define_stmt->definition) > 0)
+ {
+ deparseDefinition(str, define_stmt->definition);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCompositeTypeStmt(StringInfo str, CompositeTypeStmt *composite_type_stmt)
+{
+ ListCell *lc;
+ RangeVar *typevar;
+
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseRangeVar(str, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
+
+ appendStringInfoString(str, " AS (");
+ foreach(lc, composite_type_stmt->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(composite_type_stmt->coldeflist, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateEnumStmt(StringInfo str, CreateEnumStmt *create_enum_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE TYPE ");
+
+ deparseAnyName(str, create_enum_stmt->typeName);
+ appendStringInfoString(str, " AS ENUM (");
+ foreach(lc, create_enum_stmt->vals)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(create_enum_stmt->vals, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateRangeStmt(StringInfo str, CreateRangeStmt *create_range_stmt)
+{
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseAnyName(str, create_range_stmt->typeName);
+ appendStringInfoString(str, " AS RANGE ");
+ deparseDefinition(str, create_range_stmt->params);
+}
+
+static void deparseAlterEnumStmt(StringInfo str, AlterEnumStmt *alter_enum_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_enum_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->oldVal == NULL)
+ {
+ appendStringInfoString(str, "ADD VALUE ");
+ if (alter_enum_stmt->skipIfNewValExists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->newValNeighbor)
+ {
+ if (alter_enum_stmt->newValIsAfter)
+ appendStringInfoString(str, "AFTER ");
+ else
+ appendStringInfoString(str, "BEFORE ");
+ deparseStringLiteral(str, alter_enum_stmt->newValNeighbor);
+ }
+ }
+ else
+ {
+ appendStringInfoString(str, "RENAME VALUE ");
+ deparseStringLiteral(str, alter_enum_stmt->oldVal);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionStmt(StringInfo str, AlterExtensionStmt *alter_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_stmt->extname);
+ appendStringInfoString(str, " UPDATE ");
+ foreach (lc, alter_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionContentsStmt(StringInfo str, AlterExtensionContentsStmt *alter_extension_contents_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_contents_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_extension_contents_stmt->action == 1)
+ appendStringInfoString(str, "ADD ");
+ else if (alter_extension_contents_stmt->action == -1)
+ appendStringInfoString(str, "DROP ");
+ else
+ Assert(false);
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ // No other object types are supported here in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ // any_name
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_TABLE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ deparseAnyName(str, castNode(List, alter_extension_contents_stmt->object));
+ break;
+ // name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_LANGUAGE:
+ case OBJECT_SCHEMA:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ deparseColId(str, strVal(alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ deparseTypeName(str, castNode(TypeName, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
+{
+ ListCell *lc;
+
+ if (access_priv->priv_name != NULL)
+ {
+ if (strcmp(access_priv->priv_name, "select") == 0)
+ appendStringInfoString(str, "select");
+ else if (strcmp(access_priv->priv_name, "references") == 0)
+ appendStringInfoString(str, "references");
+ else if (strcmp(access_priv->priv_name, "create") == 0)
+ appendStringInfoString(str, "create");
+ else
+ appendStringInfoString(str, quote_identifier(access_priv->priv_name));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(access_priv->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, access_priv->cols);
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
+{
+ ListCell *lc;
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "GRANT OPTION FOR ");
+
+ if (list_length(grant_stmt->privileges) > 0)
+ {
+ foreach(lc, grant_stmt->privileges)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_stmt->privileges, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ deparsePrivilegeTarget(str, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ foreach(lc, grant_stmt->grantees)
+ {
+ deparseRoleSpec(str, castNode(RoleSpec, lfirst(lc)));
+ if (lnext(grant_stmt->grantees, lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "WITH GRANT OPTION ");
+
+ deparseOptDropBehavior(str, grant_stmt->behavior);
+
+ if (grant_stmt->grantor)
+ {
+ appendStringInfoString(str, "GRANTED BY ");
+ deparseRoleSpec(str, castNode(RoleSpec, grant_stmt->grantor));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
+{
+ ListCell *lc;
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_role_stmt->is_grant && grant_role_stmt->admin_opt)
+ appendStringInfoString(str, "ADMIN OPTION FOR ");
+
+ foreach(lc, grant_role_stmt->granted_roles)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_role_stmt->granted_roles, lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ deparseRoleList(str, grant_role_stmt->grantee_roles);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_role_stmt->is_grant && grant_role_stmt->admin_opt)
+ appendStringInfoString(str, "WITH ADMIN OPTION ");
+
+ if (grant_role_stmt->grantor)
+ {
+ appendStringInfoString(str, "GRANTED BY ");
+ deparseRoleSpec(str, castNode(RoleSpec, grant_role_stmt->grantor));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropRoleStmt(StringInfo str, DropRoleStmt *drop_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DROP ROLE ");
+
+ if (drop_role_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRoleList(str, drop_role_stmt->roles);
+}
+
+static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (index_stmt->unique)
+ appendStringInfoString(str, "UNIQUE ");
+
+ appendStringInfoString(str, "INDEX ");
+
+ if (index_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (index_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (index_stmt->idxname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(index_stmt->idxname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (index_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(index_stmt->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, index_stmt->indexParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+
+ if (list_length(index_stmt->indexIncludingParams) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ foreach (lc, index_stmt->indexIncludingParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexIncludingParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ if (index_stmt->nulls_not_distinct)
+ {
+ appendStringInfoString(str, "NULLS NOT DISTINCT ");
+ }
+
+ deparseOptWith(str, index_stmt->options);
+
+ if (index_stmt->tableSpace != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(index_stmt->tableSpace));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, index_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterOpFamilyStmt(StringInfo str, AlterOpFamilyStmt *alter_op_family_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR FAMILY ");
+ deparseAnyName(str, alter_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(alter_op_family_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_op_family_stmt->isDrop)
+ appendStringInfoString(str, "DROP ");
+ else
+ appendStringInfoString(str, "ADD ");
+
+ deparseOpclassItemList(str, alter_op_family_stmt->items);
+}
+
+static void deparsePrepareStmt(StringInfo str, PrepareStmt *prepare_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "PREPARE ");
+ deparseColId(str, prepare_stmt->name);
+ if (list_length(prepare_stmt->argtypes) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, prepare_stmt->argtypes);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoString(str, " AS ");
+ deparsePreparableStmt(str, prepare_stmt->query);
+}
+
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "EXECUTE ");
+ appendStringInfoString(str, quote_identifier(execute_stmt->name));
+ if (list_length(execute_stmt->params) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, execute_stmt->params);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseDeallocateStmt(StringInfo str, DeallocateStmt *deallocate_stmt)
+{
+ appendStringInfoString(str, "DEALLOCATE ");
+ if (deallocate_stmt->name != NULL)
+ appendStringInfoString(str, quote_identifier(deallocate_stmt->name));
+ else
+ appendStringInfoString(str, "ALL");
+}
+
+// "AlterOptRoleElem" in gram.y
+static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "password") == 0)
+ {
+ appendStringInfoString(str, "PASSWORD ");
+ if (def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NULL");
+ }
+ else if (IsA(def_elem->arg, ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "connectionlimit") == 0)
+ {
+ appendStringInfo(str, "CONNECTION LIMIT %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validUntil") == 0)
+ {
+ appendStringInfoString(str, "VALID UNTIL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "SUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOSUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "CREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOCREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "REPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOREPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "CREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOCREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "LOGIN");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOLOGIN");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "BYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOBYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "INHERIT");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOINHERIT");
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "CreateOptRoleElem" in gram.y
+static void deparseCreateRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "sysid") == 0)
+ {
+ appendStringInfo(str, "SYSID %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "adminmembers") == 0)
+ {
+ appendStringInfoString(str, "ADMIN ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "addroleto") == 0)
+ {
+ appendStringInfoString(str, "IN ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ deparseAlterRoleElem(str, def_elem);
+ }
+}
+
+static void deparseCreatePLangStmt(StringInfo str, CreatePLangStmt *create_p_lang_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+
+ if (create_p_lang_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ if (create_p_lang_stmt->pltrusted)
+ appendStringInfoString(str, "TRUSTED ");
+
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, create_p_lang_stmt->plname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_p_lang_stmt->plhandler);
+ appendStringInfoChar(str, ' ');
+
+ if (create_p_lang_stmt->plinline)
+ {
+ appendStringInfoString(str, "INLINE ");
+ deparseHandlerName(str, create_p_lang_stmt->plinline);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_p_lang_stmt->plvalidator)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, create_p_lang_stmt->plvalidator);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateRoleStmt(StringInfo str, CreateRoleStmt *create_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ switch (create_role_stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case ROLESTMT_USER:
+ appendStringInfoString(str, "USER ");
+ break;
+ case ROLESTMT_GROUP:
+ appendStringInfoString(str, "GROUP ");
+ break;
+ }
+
+ appendStringInfoString(str, quote_identifier(create_role_stmt->role));
+ appendStringInfoChar(str, ' ');
+
+ if (create_role_stmt->options != NULL)
+ {
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, create_role_stmt->options)
+ {
+ deparseCreateRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleStmt(StringInfo str, AlterRoleStmt *alter_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "GROUP ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_stmt->action == 1)
+ {
+ appendStringInfoString(str, "ADD USER ");
+ }
+ else if (alter_role_stmt->action == -1)
+ {
+ appendStringInfoString(str, "DROP USER ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseRoleList(str, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, alter_role_stmt->options)
+ {
+ deparseAlterRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeclareCursorStmt(StringInfo str, DeclareCursorStmt *declare_cursor_stmt)
+{
+ appendStringInfoString(str, "DECLARE ");
+ appendStringInfoString(str, quote_identifier(declare_cursor_stmt->portalname));
+ appendStringInfoChar(str, ' ');
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
+ appendStringInfoString(str, "BINARY ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
+ appendStringInfoString(str, "SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
+ appendStringInfoString(str, "NO SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
+ appendStringInfoString(str, "INSENSITIVE ");
+
+ appendStringInfoString(str, "CURSOR ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
+ appendStringInfoString(str, "WITH HOLD ");
+
+ appendStringInfoString(str, "FOR ");
+
+ deparseSelectStmt(str, castNode(SelectStmt, declare_cursor_stmt->query));
+}
+
+static void deparseFetchStmt(StringInfo str, FetchStmt *fetch_stmt)
+{
+ if (fetch_stmt->ismove)
+ appendStringInfoString(str, "MOVE ");
+ else
+ appendStringInfoString(str, "FETCH ");
+
+ switch (fetch_stmt->direction)
+ {
+ case FETCH_FORWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ // Default
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "FORWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_BACKWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "PRIOR ");
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "BACKWARD ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "BACKWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_ABSOLUTE:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "FIRST ");
+ }
+ else if (fetch_stmt->howMany == -1)
+ {
+ appendStringInfoString(str, "LAST ");
+ }
+ else
+ {
+ appendStringInfo(str, "ABSOLUTE %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_RELATIVE:
+ appendStringInfo(str, "RELATIVE %ld ", fetch_stmt->howMany);
+ }
+
+ appendStringInfoString(str, fetch_stmt->portalname);
+}
+
+static void deparseAlterDefaultPrivilegesStmt(StringInfo str, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER DEFAULT PRIVILEGES ");
+
+ foreach (lc, alter_default_privileges_stmt->options)
+ {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp(defelem->defname, "schemas") == 0)
+ {
+ appendStringInfoString(str, "IN SCHEMA ");
+ deparseNameList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defelem->defname, "roles") == 0)
+ {
+ appendStringInfoString(str, "FOR ROLE ");
+ deparseRoleList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ // No other DefElems are supported
+ Assert(false);
+ }
+ }
+
+ deparseGrantStmt(str, alter_default_privileges_stmt->action);
+}
+
+static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
+{
+ appendStringInfoString(str, "REINDEX ");
+
+ deparseUtilityOptionList(str, reindex_stmt->params);
+
+ switch (reindex_stmt->kind)
+ {
+ case REINDEX_OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case REINDEX_OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case REINDEX_OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case REINDEX_OBJECT_SYSTEM:
+ appendStringInfoString(str, "SYSTEM ");
+ break;
+ case REINDEX_OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ }
+
+ if (reindex_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (reindex_stmt->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(reindex_stmt->name));
+ }
+}
+
+static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (rule_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "RULE ");
+ appendStringInfoString(str, quote_identifier(rule_stmt->rulename));
+ appendStringInfoString(str, " AS ON ");
+
+ switch (rule_stmt->event)
+ {
+ case CMD_UNKNOWN:
+ case CMD_UTILITY:
+ case CMD_NOTHING:
+ // Not supported here
+ Assert(false);
+ break;
+ case CMD_SELECT:
+ appendStringInfoString(str, "SELECT ");
+ break;
+ case CMD_UPDATE:
+ appendStringInfoString(str, "UPDATE ");
+ break;
+ case CMD_INSERT:
+ appendStringInfoString(str, "INSERT ");
+ break;
+ case CMD_DELETE:
+ appendStringInfoString(str, "DELETE ");
+ break;
+ case CMD_MERGE:
+ appendStringInfoString(str, "MERGE ");
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ deparseRangeVar(str, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseWhereClause(str, rule_stmt->whereClause);
+
+ appendStringInfoString(str, "DO ");
+
+ if (rule_stmt->instead)
+ appendStringInfoString(str, "INSTEAD ");
+
+ if (list_length(rule_stmt->actions) == 0)
+ {
+ appendStringInfoString(str, "NOTHING");
+ }
+ else if (list_length(rule_stmt->actions) == 1)
+ {
+ deparseRuleActionStmt(str, linitial(rule_stmt->actions));
+ }
+ else
+ {
+ appendStringInfoChar(str, '(');
+ foreach (lc, rule_stmt->actions)
+ {
+ deparseRuleActionStmt(str, lfirst(lc));
+ if (lnext(rule_stmt->actions, lc))
+ appendStringInfoString(str, "; ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseNotifyStmt(StringInfo str, NotifyStmt *notify_stmt)
+{
+ appendStringInfoString(str, "NOTIFY ");
+ appendStringInfoString(str, quote_identifier(notify_stmt->conditionname));
+
+ if (notify_stmt->payload != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseStringLiteral(str, notify_stmt->payload);
+ }
+}
+
+static void deparseListenStmt(StringInfo str, ListenStmt *listen_stmt)
+{
+ appendStringInfoString(str, "LISTEN ");
+ appendStringInfoString(str, quote_identifier(listen_stmt->conditionname));
+}
+
+static void deparseUnlistenStmt(StringInfo str, UnlistenStmt *unlisten_stmt)
+{
+ appendStringInfoString(str, "UNLISTEN ");
+ if (unlisten_stmt->conditionname == NULL)
+ appendStringInfoString(str, "*");
+ else
+ appendStringInfoString(str, quote_identifier(unlisten_stmt->conditionname));
+}
+
+static void deparseCreateSeqStmt(StringInfo str, CreateSeqStmt *create_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_seq_stmt->sequence->relpersistence);
+
+ appendStringInfoString(str, "SEQUENCE ");
+
+ if (create_seq_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptSeqOptList(str, create_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFunctionStmt(StringInfo str, AlterFunctionStmt *alter_function_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_function_stmt->objtype)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ deparseFunctionWithArgtypes(str, alter_function_stmt->func);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, alter_function_stmt->actions)
+ {
+ deparseCommonFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ if (lnext(alter_function_stmt->actions, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseTruncateStmt(StringInfo str, TruncateStmt *truncate_stmt)
+{
+ appendStringInfoString(str, "TRUNCATE ");
+
+ deparseRelationExprList(str, truncate_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (truncate_stmt->restart_seqs)
+ appendStringInfoString(str, "RESTART IDENTITY ");
+
+ deparseOptDropBehavior(str, truncate_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateEventTrigStmt(StringInfo str, CreateEventTrigStmt *create_event_trig_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "CREATE EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "ON ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->eventname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_event_trig_stmt->whenclause)
+ {
+ appendStringInfoString(str, "WHEN ");
+
+ foreach (lc, create_event_trig_stmt->whenclause)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " IN (");
+ foreach (lc2, l)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ if (lnext(create_event_trig_stmt->whenclause, lc))
+ appendStringInfoString(str, " AND ");
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_event_trig_stmt->funcname);
+ appendStringInfoString(str, "()");
+}
+
+static void deparseAlterEventTrigStmt(StringInfo str, AlterEventTrigStmt *alter_event_trig_stmt)
+{
+ appendStringInfoString(str, "ALTER EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(alter_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_event_trig_stmt->tgenabled)
+ {
+ case TRIGGER_FIRES_ON_ORIGIN:
+ appendStringInfoString(str, "ENABLE");
+ break;
+ case TRIGGER_FIRES_ON_REPLICA:
+ appendStringInfoString(str, "ENABLE REPLICA");
+ break;
+ case TRIGGER_FIRES_ALWAYS:
+ appendStringInfoString(str, "ENABLE ALWAYS");
+ break;
+ case TRIGGER_DISABLED:
+ appendStringInfoString(str, "DISABLE");
+ break;
+ }
+}
+
+static void deparseRefreshMatViewStmt(StringInfo str, RefreshMatViewStmt *refresh_mat_view_stmt)
+{
+ appendStringInfoString(str, "REFRESH MATERIALIZED VIEW ");
+
+ if (refresh_mat_view_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ deparseRangeVar(str, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (refresh_mat_view_stmt->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt)
+{
+ switch (replica_identity_stmt->identity_type)
+ {
+ case REPLICA_IDENTITY_NOTHING:
+ appendStringInfoString(str, "NOTHING ");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ appendStringInfoString(str, "FULL ");
+ break;
+ case REPLICA_IDENTITY_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ Assert(replica_identity_stmt->name != NULL);
+ appendStringInfoString(str, "USING INDEX ");
+ appendStringInfoString(str, quote_identifier(replica_identity_stmt->name));
+ break;
+ }
+}
+
+static void deparseCreatePolicyStmt(StringInfo str, CreatePolicyStmt *create_policy_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE POLICY ");
+ deparseColId(str, create_policy_stmt->policy_name);
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (!create_policy_stmt->permissive)
+ appendStringInfoString(str, "AS RESTRICTIVE ");
+
+ if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
+ Assert(true); // Default
+ else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
+ appendStringInfoString(str, "FOR SELECT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
+ appendStringInfoString(str, "FOR INSERT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
+ appendStringInfoString(str, "FOR UPDATE ");
+ else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
+ appendStringInfoString(str, "FOR DELETE ");
+ else
+ Assert(false);
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, create_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ if (create_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, create_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (create_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, create_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseAlterPolicyStmt(StringInfo str, AlterPolicyStmt *alter_policy_stmt)
+{
+ appendStringInfoString(str, "ALTER POLICY ");
+ appendStringInfoString(str, quote_identifier(alter_policy_stmt->policy_name));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_policy_stmt->roles) > 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, alter_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, alter_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (alter_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, alter_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *create_table_space_stmt)
+{
+ appendStringInfoString(str, "CREATE TABLESPACE ");
+ deparseColId(str, create_table_space_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_space_stmt->owner != NULL)
+ {
+ appendStringInfoString(str, "OWNER ");
+ deparseRoleSpec(str, create_table_space_stmt->owner);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "LOCATION ");
+
+ if (create_table_space_stmt->location != NULL)
+ deparseStringLiteral(str, create_table_space_stmt->location);
+ else
+ appendStringInfoString(str, "''");
+
+ appendStringInfoChar(str, ' ');
+
+ deparseOptWith(str, create_table_space_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTransformStmt(StringInfo str, CreateTransformStmt *create_transform_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_transform_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "TRANSFORM FOR ");
+ deparseTypeName(str, create_transform_stmt->type_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(create_transform_stmt->lang));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoChar(str, '(');
+
+ if (create_transform_stmt->fromsql)
+ {
+ appendStringInfoString(str, "FROM SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->fromsql);
+ }
+
+ if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
+ appendStringInfoString(str, ", ");
+
+ if (create_transform_stmt->tosql)
+ {
+ appendStringInfoString(str, "TO SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->tosql);
+ }
+
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
+{
+ appendStringInfoString(str, "CREATE ACCESS METHOD ");
+ appendStringInfoString(str, quote_identifier(create_am_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TYPE ");
+ switch (create_am_stmt->amtype)
+ {
+ case AMTYPE_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case AMTYPE_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ }
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_am_stmt->handler_name);
+}
+
+static void deparsePublicationObjectList(StringInfo str, List *pubobjects) {
+ const ListCell *lc;
+ foreach(lc, pubobjects) {
+ PublicationObjSpec *obj = lfirst(lc);
+
+ switch (obj->pubobjtype) {
+ case PUBLICATIONOBJ_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ deparseRangeVar(str, obj->pubtable->relation, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (obj->pubtable->columns)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, obj->pubtable->columns);
+ appendStringInfoChar(str, ')');
+ }
+
+ if (obj->pubtable->whereClause)
+ {
+ appendStringInfoString(str, " WHERE (");
+ deparseExpr(str, obj->pubtable->whereClause);
+ appendStringInfoString(str, ")");
+ }
+
+ break;
+ case PUBLICATIONOBJ_TABLES_IN_SCHEMA:
+ appendStringInfoString(str, "TABLES IN SCHEMA ");
+ appendStringInfoString(str, quote_identifier(obj->name));
+ break;
+ case PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA:
+ appendStringInfoString(str, "TABLES IN SCHEMA CURRENT_SCHEMA");
+ break;
+ case PUBLICATIONOBJ_CONTINUATION:
+ // This should be unreachable, the parser merges these before we can even get here.
+ Assert(false);
+ break;
+ }
+
+ if (lnext(pubobjects, lc)) {
+ appendStringInfoString(str, ", ");
+ }
+ }
+}
+
+static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_publication_stmt->pubobjects) > 0)
+ {
+ appendStringInfoString(str, "FOR ");
+ deparsePublicationObjectList(str, create_publication_stmt->pubobjects);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_publication_stmt->for_all_tables)
+ {
+ appendStringInfoString(str, "FOR ALL TABLES ");
+ }
+
+ deparseOptDefinition(str, create_publication_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *alter_publication_stmt)
+{
+ appendStringInfoString(str, "ALTER PUBLICATION ");
+ deparseColId(str, alter_publication_stmt->pubname);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_publication_stmt->pubobjects) > 0)
+ {
+ switch (alter_publication_stmt->action)
+ {
+ case AP_SetObjects:
+ appendStringInfoString(str, "SET ");
+ break;
+ case AP_AddObjects:
+ appendStringInfoString(str, "ADD ");
+ break;
+ case AP_DropObjects:
+ appendStringInfoString(str, "DROP ");
+ break;
+ }
+
+ deparsePublicationObjectList(str, alter_publication_stmt->pubobjects);
+ }
+ else if (list_length(alter_publication_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_publication_stmt->options);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+static void deparseAlterSeqStmt(StringInfo str, AlterSeqStmt *alter_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SEQUENCE ");
+
+ if (alter_seq_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseSeqOptList(str, alter_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSystemStmt(StringInfo str, AlterSystemStmt *alter_system_stmt)
+{
+ appendStringInfoString(str, "ALTER SYSTEM ");
+ deparseVariableSetStmt(str, alter_system_stmt->setstmt);
+}
+
+static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "COMMENT ON ");
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ deparseAnyName(str, castNode(List, comment_stmt->object));
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(strVal(comment_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ deparseTypeName(str, castNode(TypeName, comment_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON DOMAIN ");
+ deparseTypeName(str, linitial(l));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(lsecond(l))));
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, comment_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseValue(str, (union ValUnion *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (comment_stmt->comment != NULL)
+ deparseStringLiteral(str, comment_stmt->comment);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseStatsElem(StringInfo str, StatsElem *stats_elem)
+{
+ // only one of stats_elem->name or stats_elem->expr can be non-null
+ if (stats_elem->name)
+ appendStringInfoString(str, stats_elem->name);
+ else if (stats_elem->expr)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, stats_elem->expr);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE STATISTICS ");
+
+ if (create_stats_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseAnyName(str, create_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_stats_stmt->stat_types) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, create_stats_stmt->stat_types);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ foreach (lc, create_stats_stmt->exprs)
+ {
+ deparseStatsElem(str, lfirst(lc));
+ if (lnext(create_stats_stmt->exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, " FROM ");
+ deparseFromList(str, create_stats_stmt->relations);
+}
+
+static void deparseAlterCollationStmt(StringInfo str, AlterCollationStmt *alter_collation_stmt)
+{
+ appendStringInfoString(str, "ALTER COLLATION ");
+ deparseAnyName(str, alter_collation_stmt->collname);
+ appendStringInfoString(str, " REFRESH VERSION");
+}
+
+static void deparseAlterDatabaseStmt(StringInfo str, AlterDatabaseStmt *alter_database_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, alter_database_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterDatabaseSetStmt(StringInfo str, AlterDatabaseSetStmt *alter_database_set_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_set_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseVariableSetStmt(str, alter_database_set_stmt->setstmt);
+}
+
+static void deparseAlterStatsStmt(StringInfo str, AlterStatsStmt *alter_stats_stmt)
+{
+ appendStringInfoString(str, "ALTER STATISTICS ");
+
+ if (alter_stats_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseAnyName(str, alter_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfo(str, "SET STATISTICS %d", alter_stats_stmt->stxstattarget);
+}
+
+static void deparseAlterTSDictionaryStmt(StringInfo str, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
+{
+ appendStringInfoString(str, "ALTER TEXT SEARCH DICTIONARY ");
+
+ deparseAnyName(str, alter_ts_dictionary_stmt->dictname);
+ appendStringInfoChar(str, ' ');
+
+ deparseDefinition(str, alter_ts_dictionary_stmt->options);
+}
+
+static void deparseAlterTSConfigurationStmt(StringInfo str, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, alter_ts_configuration_stmt->cfgname);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_ts_configuration_stmt->kind)
+ {
+ case ALTER_TSCONFIG_ADD_MAPPING:
+ appendStringInfoString(str, "ADD MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT:
+ appendStringInfoString(str, "ALTER MAPPING REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_DROP_MAPPING:
+ appendStringInfoString(str, "DROP MAPPING ");
+ if (alter_ts_configuration_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, "FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ break;
+ }
+}
+
+static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_show_stmt)
+{
+ appendStringInfoString(str, "SHOW ");
+
+ if (strcmp(variable_show_stmt->name, "timezone") == 0)
+ appendStringInfoString(str, "TIME ZONE");
+ else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
+ appendStringInfoString(str, "TRANSACTION ISOLATION LEVEL");
+ else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
+ appendStringInfoString(str, "SESSION AUTHORIZATION");
+ else if (strcmp(variable_show_stmt->name, "all") == 0)
+ appendStringInfoString(str, "ALL");
+ else
+ appendStringInfoString(str, quote_identifier(variable_show_stmt->name));
+}
+
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
+{
+ deparseRangeVar(str, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
+
+ appendStringInfoString(str, " TABLESAMPLE ");
+
+ deparseFuncName(str, range_table_sample->method);
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, range_table_sample->args);
+ appendStringInfoString(str, ") ");
+
+ if (range_table_sample->repeatable != NULL)
+ {
+ appendStringInfoString(str, "REPEATABLE (");
+ deparseExpr(str, range_table_sample->repeatable);
+ appendStringInfoString(str, ") ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateSubscriptionStmt(StringInfo str, CreateSubscriptionStmt *create_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(create_subscription_stmt->subname));
+
+ appendStringInfoString(str, " CONNECTION ");
+ if (create_subscription_stmt->conninfo != NULL)
+ deparseStringLiteral(str, create_subscription_stmt->conninfo);
+ else
+ appendStringInfoString(str, "''");
+
+ appendStringInfoString(str, " PUBLICATION ");
+
+ foreach(lc, create_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(create_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDefinition(str, create_subscription_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *alter_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(alter_subscription_stmt->subname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_subscription_stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SKIP:
+ appendStringInfoString(str, "SKIP ");
+ deparseDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ appendStringInfoString(str, "CONNECTION ");
+ deparseStringLiteral(str, alter_subscription_stmt->conninfo);
+ appendStringInfoChar(str, ' ');
+ break;
+ case ALTER_SUBSCRIPTION_REFRESH:
+ appendStringInfoString(str, "REFRESH PUBLICATION ");
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ADD_PUBLICATION:
+ appendStringInfoString(str, "ADD PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_DROP_PUBLICATION:
+ appendStringInfoString(str, "DROP PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SET_PUBLICATION:
+ appendStringInfoString(str, "SET PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ENABLED:
+ Assert(list_length(alter_subscription_stmt->options) == 1);
+ DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
+ Assert(strcmp(defelem->defname, "enabled") == 0);
+ if (optBooleanValue(defelem->arg))
+ {
+ appendStringInfoString(str, " ENABLE ");
+ }
+ else
+ {
+ appendStringInfoString(str, " DISABLE ");
+ }
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropSubscriptionStmt(StringInfo str, DropSubscriptionStmt *drop_subscription_stmt)
+{
+ appendStringInfoString(str, "DROP SUBSCRIPTION ");
+
+ if (drop_subscription_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_subscription_stmt->subname);
+}
+
+static void deparseCallStmt(StringInfo str, CallStmt *call_stmt)
+{
+ appendStringInfoString(str, "CALL ");
+ deparseFuncCall(str, call_stmt->funccall);
+}
+
+static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_owner_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnly(str, (union ValUnion *) alter_owner_stmt->object);
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ default:
+ Assert(false);
+ }
+
+ appendStringInfoString(str, " OWNER TO ");
+ deparseRoleSpec(str, alter_owner_stmt->newowner);
+}
+
+// "operator_def_list" in gram.y
+static void deparseOperatorDefList(StringInfo str, List *defs)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, defs)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " = ");
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, true);
+ else
+ appendStringInfoString(str, "NONE");
+
+ if (lnext(defs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterOperatorStmt(StringInfo str, AlterOperatorStmt *alter_operator_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR ");
+ deparseOperatorWithArgtypes(str, alter_operator_stmt->opername);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_operator_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseAlterTypeStmt(StringInfo str, AlterTypeStmt *alter_type_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_type_stmt->typeName);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_type_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseDropOwnedStmt(StringInfo str, DropOwnedStmt *drop_owned_stmt)
+{
+ appendStringInfoString(str, "DROP OWNED BY ");
+ deparseRoleList(str, drop_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ deparseOptDropBehavior(str, drop_owned_stmt->behavior);
+ removeTrailingSpace(str);
+}
+
+static void deparseReassignOwnedStmt(StringInfo str, ReassignOwnedStmt *reassigned_owned_stmt)
+{
+ appendStringInfoString(str, "REASSIGN OWNED BY ");
+
+ deparseRoleList(str, reassigned_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleSpec(str, reassigned_owned_stmt->newrole);
+}
+
+static void deparseClosePortalStmt(StringInfo str, ClosePortalStmt *close_portal_stmt)
+{
+ appendStringInfoString(str, "CLOSE ");
+ if (close_portal_stmt->portalname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(close_portal_stmt->portalname));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+}
+
+static void deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr)
+{
+ appendStringInfoString(str, "CURRENT OF ");
+ appendStringInfoString(str, quote_identifier(current_of_expr->cursor_name));
+}
+
+static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_stmt)
+{
+ ListCell *lc;
+ bool skip_events_or = true;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_trig_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_trig_stmt->isconstraint)
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, "TRIGGER ");
+
+ appendStringInfoString(str, quote_identifier(create_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (create_trig_stmt->timing)
+ {
+ case TRIGGER_TYPE_BEFORE:
+ appendStringInfoString(str, "BEFORE ");
+ break;
+ case TRIGGER_TYPE_AFTER:
+ appendStringInfoString(str, "AFTER ");
+ break;
+ case TRIGGER_TYPE_INSTEAD:
+ appendStringInfoString(str, "INSTEAD OF ");
+ break;
+ default:
+ Assert(false);
+ }
+
+ if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
+ {
+ appendStringInfoString(str, "INSERT ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "DELETE ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "UPDATE ");
+ if (list_length(create_trig_stmt->columns) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseColumnList(str, create_trig_stmt->columns);
+ appendStringInfoChar(str, ' ');
+ }
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "TRUNCATE ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_trig_stmt->transitionRels != NULL)
+ {
+ appendStringInfoString(str, "REFERENCING ");
+ foreach(lc, create_trig_stmt->transitionRels)
+ {
+ deparseTriggerTransition(str, castNode(TriggerTransition, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ if (create_trig_stmt->constrrel != NULL)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseRangeVar(str, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_trig_stmt->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (create_trig_stmt->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (create_trig_stmt->row)
+ appendStringInfoString(str, "FOR EACH ROW ");
+
+ if (create_trig_stmt->whenClause)
+ {
+ appendStringInfoString(str, "WHEN (");
+ deparseExpr(str, create_trig_stmt->whenClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_trig_stmt->funcname);
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_trig_stmt->args)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(create_trig_stmt->args, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition)
+{
+ if (trigger_transition->isNew)
+ appendStringInfoString(str, "NEW ");
+ else
+ appendStringInfoString(str, "OLD ");
+
+ if (trigger_transition->isTable)
+ appendStringInfoString(str, "TABLE ");
+ else
+ appendStringInfoString(str, "ROW ");
+
+ appendStringInfoString(str, quote_identifier(trigger_transition->name));
+}
+
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
+{
+ switch (xml_expr->op)
+ {
+ case IS_XMLCONCAT: /* XMLCONCAT(args) */
+ appendStringInfoString(str, "xmlconcat(");
+ deparseExprList(str, xml_expr->args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
+ appendStringInfoString(str, "xmlelement(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->named_args != NULL)
+ {
+ appendStringInfoString(str, ", xmlattributes(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoString(str, ")");
+ }
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExprList(str, xml_expr->args);
+ }
+ appendStringInfoString(str, ")");
+ break;
+ case IS_XMLFOREST: /* XMLFOREST(xml_attributes) */
+ appendStringInfoString(str, "xmlforest(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
+ Assert(list_length(xml_expr->args) == 2);
+ appendStringInfoString(str, "xmlparse(");
+ switch (xml_expr->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPI: /* XMLPI(name [, args]) */
+ appendStringInfoString(str, "xmlpi(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, linitial(xml_expr->args));
+ }
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
+ appendStringInfoString(str, "xmlroot(");
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, ", version ");
+ if (castNode(A_Const, lsecond(xml_expr->args))->isnull)
+ appendStringInfoString(str, "NO VALUE");
+ else
+ deparseExpr(str, lsecond(xml_expr->args));
+ if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
+ appendStringInfoString(str, ", STANDALONE YES");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
+ appendStringInfoString(str, ", STANDALONE NO");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
+ appendStringInfoString(str, ", STANDALONE NO VALUE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLSERIALIZE: /* XMLSERIALIZE(is_document, xmlval) */
+ // These are represented as XmlSerialize in raw parse trees
+ Assert(false);
+ break;
+ case IS_DOCUMENT: /* xmlval IS DOCUMENT */
+ Assert(list_length(xml_expr->args) == 1);
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, " IS DOCUMENT");
+ break;
+ }
+}
+
+static void deparseRangeTableFuncCol(StringInfo str, RangeTableFuncCol* range_table_func_col)
+{
+ appendStringInfoString(str, quote_identifier(range_table_func_col->colname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->for_ordinality)
+ {
+ appendStringInfoString(str, "FOR ORDINALITY ");
+ }
+ else
+ {
+ deparseTypeName(str, range_table_func_col->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->colexpr)
+ {
+ appendStringInfoString(str, "PATH ");
+ deparseExpr(str, range_table_func_col->colexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->coldefexpr)
+ {
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, range_table_func_col->coldefexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->is_not_null)
+ appendStringInfoString(str, "NOT NULL ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func)
+{
+ ListCell *lc;
+
+ if (range_table_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoString(str, "xmltable(");
+ if (range_table_func->namespaces)
+ {
+ appendStringInfoString(str, "xmlnamespaces(");
+ deparseXmlNamespaceList(str, range_table_func->namespaces);
+ appendStringInfoString(str, "), ");
+ }
+
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, range_table_func->rowexpr);
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, range_table_func->docexpr);
+
+ appendStringInfoString(str, " COLUMNS ");
+ foreach(lc, range_table_func->columns)
+ {
+ deparseRangeTableFuncCol(str, castNode(RangeTableFuncCol, lfirst(lc)));
+ if (lnext(range_table_func->columns, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, ") ");
+
+ if (range_table_func->alias)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_table_func->alias);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize)
+{
+ appendStringInfoString(str, "xmlserialize(");
+ switch (xml_serialize->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, xml_serialize->expr);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, xml_serialize->typeName);
+ appendStringInfoString(str, ")");
+}
+
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
+{
+ appendStringInfoString(str, "GROUPING(");
+ deparseExprList(str, grouping_func->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
+{
+ appendStringInfoString(str, "CLUSTER ");
+
+ deparseUtilityOptionList(str, cluster_stmt->params);
+
+ if (cluster_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (cluster_stmt->indexname != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(cluster_stmt->indexname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context)
+{
+ if (!value) {
+ appendStringInfoString(str, "NULL");
+ return;
+ }
+
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ case T_Float:
+ deparseNumericOnly(str, value);
+ break;
+ case T_Boolean:
+ appendStringInfoString(str, value->boolval.boolval ? "true" : "false");
+ break;
+ case T_String:
+ if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
+ appendStringInfoString(str, quote_identifier(value->sval.sval));
+ } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
+ deparseStringLiteral(str, value->sval.sval);
+ } else {
+ appendStringInfoString(str, value->sval.sval);
+ }
+ break;
+ case T_BitString:
+ if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'x')
+ {
+ appendStringInfoChar(str, 'x');
+ deparseStringLiteral(str, value->sval.sval + 1);
+ }
+ else if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'b')
+ {
+ appendStringInfoChar(str, 'b');
+ deparseStringLiteral(str, value->sval.sval + 1);
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ default:
+ elog(ERROR, "deparse: unrecognized value node type: %d",
+ (int) nodeTag(value));
+ break;
+ }
+}
+
+// "PrepareableStmt" in gram.y
+static void deparsePreparableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(str, castNode(MergeStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "RuleActionStmt" in gram.y
+static void deparseRuleActionStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "ExplainableStmt" in gram.y
+static void deparseExplainableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_CreateTableAsStmt:
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(str, castNode(MergeStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "schema_stmt" in gram.y
+static void deparseSchemaStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "stmt" in gram.y
+static void deparseStmt(StringInfo str, Node *node)
+{
+ // Note the following grammar names are missing in the list, because they
+ // get mapped to other node types:
+ //
+ // - AlterForeignTableStmt (=> AlterTableStmt)
+ // - AlterGroupStmt (=> AlterRoleStmt)
+ // - AlterCompositeTypeStmt (=> AlterTableStmt)
+ // - AnalyzeStmt (=> VacuumStmt)
+ // - CreateGroupStmt (=> CreateRoleStmt)
+ // - CreateMatViewStmt (=> CreateTableAsStmt)
+ // - CreateUserStmt (=> CreateRoleStmt)
+ // - DropCastStmt (=> DropStmt)
+ // - DropOpClassStmt (=> DropStmt)
+ // - DropOpFamilyStmt (=> DropStmt)
+ // - DropPLangStmt (=> DropPLangStmt)
+ // - DropTransformStmt (=> DropStmt)
+ // - RemoveAggrStmt (=> DropStmt)
+ // - RemoveFuncStmt (=> DropStmt)
+ // - RemoveOperStmt (=> DropStmt)
+ // - RevokeStmt (=> GrantStmt)
+ // - RevokeRoleStmt (=> GrantRoleStmt)
+ // - VariableResetStmt (=> VariableSetStmt)
+ //
+ // And the following grammar names error out in the parser:
+ // - CreateAssertionStmt (not supported yet)
+ switch (nodeTag(node))
+ {
+ case T_AlterEventTrigStmt:
+ deparseAlterEventTrigStmt(str, castNode(AlterEventTrigStmt, node));
+ break;
+ case T_AlterCollationStmt:
+ deparseAlterCollationStmt(str, castNode(AlterCollationStmt, node));
+ break;
+ case T_AlterDatabaseStmt:
+ deparseAlterDatabaseStmt(str, castNode(AlterDatabaseStmt, node));
+ break;
+ case T_AlterDatabaseSetStmt:
+ deparseAlterDatabaseSetStmt(str, castNode(AlterDatabaseSetStmt, node));
+ break;
+ case T_AlterDefaultPrivilegesStmt:
+ deparseAlterDefaultPrivilegesStmt(str, castNode(AlterDefaultPrivilegesStmt, node));
+ break;
+ case T_AlterDomainStmt:
+ deparseAlterDomainStmt(str, castNode(AlterDomainStmt, node));
+ break;
+ case T_AlterEnumStmt:
+ deparseAlterEnumStmt(str, castNode(AlterEnumStmt, node));
+ break;
+ case T_AlterExtensionStmt:
+ deparseAlterExtensionStmt(str, castNode(AlterExtensionStmt, node));
+ break;
+ case T_AlterExtensionContentsStmt:
+ deparseAlterExtensionContentsStmt(str, castNode(AlterExtensionContentsStmt, node));
+ break;
+ case T_AlterFdwStmt:
+ deparseAlterFdwStmt(str, castNode(AlterFdwStmt, node));
+ break;
+ case T_AlterForeignServerStmt:
+ deparseAlterForeignServerStmt(str, castNode(AlterForeignServerStmt, node));
+ break;
+ case T_AlterFunctionStmt:
+ deparseAlterFunctionStmt(str, castNode(AlterFunctionStmt, node));
+ break;
+ case T_AlterObjectDependsStmt:
+ deparseAlterObjectDependsStmt(str, castNode(AlterObjectDependsStmt, node));
+ break;
+ case T_AlterObjectSchemaStmt:
+ deparseAlterObjectSchemaStmt(str, castNode(AlterObjectSchemaStmt, node));
+ break;
+ case T_AlterOwnerStmt:
+ deparseAlterOwnerStmt(str, castNode(AlterOwnerStmt, node));
+ break;
+ case T_AlterOperatorStmt:
+ deparseAlterOperatorStmt(str, castNode(AlterOperatorStmt, node));
+ break;
+ case T_AlterTypeStmt:
+ deparseAlterTypeStmt(str, castNode(AlterTypeStmt, node));
+ break;
+ case T_AlterPolicyStmt:
+ deparseAlterPolicyStmt(str, castNode(AlterPolicyStmt, node));
+ break;
+ case T_AlterSeqStmt:
+ deparseAlterSeqStmt(str, castNode(AlterSeqStmt, node));
+ break;
+ case T_AlterSystemStmt:
+ deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
+ break;
+ case T_AlterTableMoveAllStmt:
+ deparseAlterTableMoveAllStmt(str, castNode(AlterTableMoveAllStmt, node));
+ break;
+ case T_AlterTableStmt:
+ deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
+ break;
+ case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
+ deparseAlterTableSpaceOptionsStmt(str, castNode(AlterTableSpaceOptionsStmt, node));
+ break;
+ case T_AlterPublicationStmt:
+ deparseAlterPublicationStmt(str, castNode(AlterPublicationStmt, node));
+ break;
+ case T_AlterRoleSetStmt:
+ deparseAlterRoleSetStmt(str, castNode(AlterRoleSetStmt, node));
+ break;
+ case T_AlterRoleStmt:
+ deparseAlterRoleStmt(str, castNode(AlterRoleStmt, node));
+ break;
+ case T_AlterSubscriptionStmt:
+ deparseAlterSubscriptionStmt(str, castNode(AlterSubscriptionStmt, node));
+ break;
+ case T_AlterStatsStmt:
+ deparseAlterStatsStmt(str, castNode(AlterStatsStmt, node));
+ break;
+ case T_AlterTSConfigurationStmt:
+ deparseAlterTSConfigurationStmt(str, castNode(AlterTSConfigurationStmt, node));
+ break;
+ case T_AlterTSDictionaryStmt:
+ deparseAlterTSDictionaryStmt(str, castNode(AlterTSDictionaryStmt, node));
+ break;
+ case T_AlterUserMappingStmt:
+ deparseAlterUserMappingStmt(str, castNode(AlterUserMappingStmt, node));
+ break;
+ case T_CallStmt:
+ deparseCallStmt(str, castNode(CallStmt, node));
+ break;
+ case T_CheckPointStmt:
+ deparseCheckPointStmt(str, castNode(CheckPointStmt, node));
+ break;
+ case T_ClosePortalStmt:
+ deparseClosePortalStmt(str, castNode(ClosePortalStmt, node));
+ break;
+ case T_ClusterStmt:
+ deparseClusterStmt(str, castNode(ClusterStmt, node));
+ break;
+ case T_CommentStmt:
+ deparseCommentStmt(str, castNode(CommentStmt, node));
+ break;
+ case T_ConstraintsSetStmt:
+ deparseConstraintsSetStmt(str, castNode(ConstraintsSetStmt, node));
+ break;
+ case T_CopyStmt:
+ deparseCopyStmt(str, castNode(CopyStmt, node));
+ break;
+ case T_CreateAmStmt:
+ deparseCreateAmStmt(str, castNode(CreateAmStmt, node));
+ break;
+ case T_CreateTableAsStmt: // "CreateAsStmt" in gram.y
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_CreateCastStmt:
+ deparseCreateCastStmt(str, castNode(CreateCastStmt, node));
+ break;
+ case T_CreateConversionStmt:
+ deparseCreateConversionStmt(str, castNode(CreateConversionStmt, node));
+ break;
+ case T_CreateDomainStmt:
+ deparseCreateDomainStmt(str, castNode(CreateDomainStmt, node));
+ break;
+ case T_CreateExtensionStmt:
+ deparseCreateExtensionStmt(str, castNode(CreateExtensionStmt, node));
+ break;
+ case T_CreateFdwStmt:
+ deparseCreateFdwStmt(str, castNode(CreateFdwStmt, node));
+ break;
+ case T_CreateForeignServerStmt:
+ deparseCreateForeignServerStmt(str, castNode(CreateForeignServerStmt, node));
+ break;
+ case T_CreateForeignTableStmt:
+ deparseCreateForeignTableStmt(str, castNode(CreateForeignTableStmt, node));
+ break;
+ case T_CreateFunctionStmt:
+ deparseCreateFunctionStmt(str, castNode(CreateFunctionStmt, node));
+ break;
+ case T_CreateOpClassStmt:
+ deparseCreateOpClassStmt(str, castNode(CreateOpClassStmt, node));
+ break;
+ case T_CreateOpFamilyStmt:
+ deparseCreateOpFamilyStmt(str, castNode(CreateOpFamilyStmt, node));
+ break;
+ case T_CreatePublicationStmt:
+ deparseCreatePublicationStmt(str, castNode(CreatePublicationStmt, node));
+ break;
+ case T_AlterOpFamilyStmt:
+ deparseAlterOpFamilyStmt(str, castNode(AlterOpFamilyStmt, node));
+ break;
+ case T_CreatePolicyStmt:
+ deparseCreatePolicyStmt(str, castNode(CreatePolicyStmt, node));
+ break;
+ case T_CreatePLangStmt:
+ deparseCreatePLangStmt(str, castNode(CreatePLangStmt, node));
+ break;
+ case T_CreateSchemaStmt:
+ deparseCreateSchemaStmt(str, castNode(CreateSchemaStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_CreateSubscriptionStmt:
+ deparseCreateSubscriptionStmt(str, castNode(CreateSubscriptionStmt, node));
+ break;
+ case T_CreateStatsStmt:
+ deparseCreateStatsStmt(str, castNode(CreateStatsStmt, node));
+ break;
+ case T_CreateTableSpaceStmt:
+ deparseCreateTableSpaceStmt(str, castNode(CreateTableSpaceStmt, node));
+ break;
+ case T_CreateTransformStmt:
+ deparseCreateTransformStmt(str, castNode(CreateTransformStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_CreateEventTrigStmt:
+ deparseCreateEventTrigStmt(str, castNode(CreateEventTrigStmt, node));
+ break;
+ case T_CreateRoleStmt:
+ deparseCreateRoleStmt(str, castNode(CreateRoleStmt, node));
+ break;
+ case T_CreateUserMappingStmt:
+ deparseCreateUserMappingStmt(str, castNode(CreateUserMappingStmt, node));
+ break;
+ case T_CreatedbStmt:
+ deparseCreatedbStmt(str, castNode(CreatedbStmt, node));
+ break;
+ case T_DeallocateStmt:
+ deparseDeallocateStmt(str, castNode(DeallocateStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_DefineStmt:
+ deparseDefineStmt(str, castNode(DefineStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DiscardStmt:
+ deparseDiscardStmt(str, castNode(DiscardStmt, node));
+ break;
+ case T_DoStmt:
+ deparseDoStmt(str, castNode(DoStmt, node));
+ break;
+ case T_DropOwnedStmt:
+ deparseDropOwnedStmt(str, castNode(DropOwnedStmt, node));
+ break;
+ case T_DropStmt:
+ deparseDropStmt(str, castNode(DropStmt, node));
+ break;
+ case T_DropSubscriptionStmt:
+ deparseDropSubscriptionStmt(str, castNode(DropSubscriptionStmt, node));
+ break;
+ case T_DropTableSpaceStmt:
+ deparseDropTableSpaceStmt(str, castNode(DropTableSpaceStmt, node));
+ break;
+ case T_DropRoleStmt:
+ deparseDropRoleStmt(str, castNode(DropRoleStmt, node));
+ break;
+ case T_DropUserMappingStmt:
+ deparseDropUserMappingStmt(str, castNode(DropUserMappingStmt, node));
+ break;
+ case T_DropdbStmt:
+ deparseDropdbStmt(str, castNode(DropdbStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ case T_ExplainStmt:
+ deparseExplainStmt(str, castNode(ExplainStmt, node));
+ break;
+ case T_FetchStmt:
+ deparseFetchStmt(str, castNode(FetchStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_GrantRoleStmt:
+ deparseGrantRoleStmt(str, castNode(GrantRoleStmt, node));
+ break;
+ case T_ImportForeignSchemaStmt:
+ deparseImportForeignSchemaStmt(str, castNode(ImportForeignSchemaStmt, node));
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_ListenStmt:
+ deparseListenStmt(str, castNode(ListenStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_LoadStmt:
+ deparseLoadStmt(str, castNode(LoadStmt, node));
+ break;
+ case T_LockStmt:
+ deparseLockStmt(str, castNode(LockStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(str, castNode(MergeStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ case T_PrepareStmt:
+ deparsePrepareStmt(str, castNode(PrepareStmt, node));
+ break;
+ case T_ReassignOwnedStmt:
+ deparseReassignOwnedStmt(str, castNode(ReassignOwnedStmt, node));
+ break;
+ case T_ReindexStmt:
+ deparseReindexStmt(str, castNode(ReindexStmt, node));
+ break;
+ case T_RenameStmt:
+ deparseRenameStmt(str, castNode(RenameStmt, node));
+ break;
+ case T_RuleStmt:
+ deparseRuleStmt(str, castNode(RuleStmt, node));
+ break;
+ case T_SecLabelStmt:
+ deparseSecLabelStmt(str, castNode(SecLabelStmt, node));
+ break;
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_TransactionStmt:
+ deparseTransactionStmt(str, castNode(TransactionStmt, node));
+ break;
+ case T_TruncateStmt:
+ deparseTruncateStmt(str, castNode(TruncateStmt, node));
+ break;
+ case T_UnlistenStmt:
+ deparseUnlistenStmt(str, castNode(UnlistenStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_VacuumStmt:
+ deparseVacuumStmt(str, castNode(VacuumStmt, node));
+ break;
+ case T_VariableSetStmt:
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, node));
+ break;
+ case T_VariableShowStmt:
+ deparseVariableShowStmt(str, castNode(VariableShowStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ // These node types are created by DefineStmt grammar for CREATE TYPE in some cases
+ case T_CompositeTypeStmt:
+ deparseCompositeTypeStmt(str, castNode(CompositeTypeStmt, node));
+ break;
+ case T_CreateEnumStmt:
+ deparseCreateEnumStmt(str, castNode(CreateEnumStmt, node));
+ break;
+ case T_CreateRangeStmt:
+ deparseCreateRangeStmt(str, castNode(CreateRangeStmt, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
+ }
+}
+#endif
diff --git a/postgres_deparse.16.c b/postgres_deparse.16.c
new file mode 100644
index 0000000..7ae9f1a
--- /dev/null
+++ b/postgres_deparse.16.c
@@ -0,0 +1,11103 @@
+#include "pg_config.h"
+#if(PG_MAJORVERSION_NUM == 16)
+
+// From https://raw.githubusercontent.com/pganalyze/libpg_query/refs/tags/16-5.2.0/src/postgres_deparse.c
+
+// Copyright (c) 2015, Lukas Fittl
+// Copyright (c) 2016-2023, Duboce Labs, Inc. (pganalyze)
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "postgres.h"
+#include "catalog/index.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_trigger.h"
+#include "commands/trigger.h"
+#include "common/keywords.h"
+#include "common/kwlookup.h"
+#include "lib/stringinfo.h"
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "utils/builtins.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/xml.h"
+
+typedef enum DeparseNodeContext {
+ DEPARSE_NODE_CONTEXT_NONE,
+ // Parent node type (and sometimes field)
+ DEPARSE_NODE_CONTEXT_INSERT_RELATION,
+ DEPARSE_NODE_CONTEXT_INSERT_ON_CONFLICT,
+ DEPARSE_NODE_CONTEXT_UPDATE,
+ DEPARSE_NODE_CONTEXT_RETURNING,
+ DEPARSE_NODE_CONTEXT_A_EXPR,
+ DEPARSE_NODE_CONTEXT_XMLATTRIBUTES,
+ DEPARSE_NODE_CONTEXT_XMLNAMESPACES,
+ DEPARSE_NODE_CONTEXT_CREATE_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_TYPE,
+ DEPARSE_NODE_CONTEXT_SET_STATEMENT,
+ DEPARSE_NODE_CONTEXT_FUNC_EXPR,
+ // Identifier vs constant context
+ DEPARSE_NODE_CONTEXT_IDENTIFIER,
+ DEPARSE_NODE_CONTEXT_CONSTANT
+} DeparseNodeContext;
+
+static void
+removeTrailingSpace(StringInfo str)
+{
+ if (str->len >= 1 && str->data[str->len - 1] == ' ') {
+ str->len -= 1;
+ str->data[str->len] = '\0';
+ }
+}
+
+/*
+ * Append a SQL string literal representing "val" to buf.
+ *
+ * Copied here from postgres_fdw/deparse.c to avoid adding
+ * many additional dependencies.
+ */
+static void
+deparseStringLiteral(StringInfo buf, const char *val)
+{
+ const char *valptr;
+
+ /*
+ * Rather than making assumptions about the remote server's value of
+ * standard_conforming_strings, always use E'foo' syntax if there are any
+ * backslashes. This will fail on remote servers before 8.1, but those
+ * are long out of support.
+ */
+ if (strchr(val, '\\') != NULL)
+ appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
+ appendStringInfoChar(buf, '\'');
+ for (valptr = val; *valptr; valptr++)
+ {
+ char ch = *valptr;
+
+ if (SQL_STR_DOUBLE(ch, true))
+ appendStringInfoChar(buf, ch);
+ appendStringInfoChar(buf, ch);
+ }
+ appendStringInfoChar(buf, '\'');
+}
+
+// Check whether the value is a reserved keyword, to determine escaping for output
+//
+// Note that since the parser lowercases all keywords, this does *not* match when the
+// value is not all-lowercase and a reserved keyword.
+static bool
+isReservedKeyword(const char *val)
+{
+ int kwnum = ScanKeywordLookup(val, &ScanKeywords);
+ bool all_lower_case = true;
+ const char *cp;
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ (*cp >= 'a' && *cp <= 'z') ||
+ (*cp >= '0' && *cp <= '9') ||
+ (*cp == '_')))
+ {
+ all_lower_case = false;
+ break;
+ }
+ }
+
+ return all_lower_case && kwnum >= 0 && ScanKeywordCategories[kwnum] == RESERVED_KEYWORD;
+}
+
+// Returns whether the given value consists only of operator characters
+static bool
+isOp(const char *val)
+{
+ const char *cp;
+
+ Assert(strlen(val) > 0);
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ *cp == '~' ||
+ *cp == '!' ||
+ *cp == '@' ||
+ *cp == '#' ||
+ *cp == '^' ||
+ *cp == '&' ||
+ *cp == '|' ||
+ *cp == '`' ||
+ *cp == '?' ||
+ *cp == '+' ||
+ *cp == '-' ||
+ *cp == '*' ||
+ *cp == '/' ||
+ *cp == '%' ||
+ *cp == '<' ||
+ *cp == '>' ||
+ *cp == '='))
+ return false;
+ }
+
+ return true;
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt);
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause);
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context);
+static void deparseResTarget(StringInfo str, ResTarget *res_target, DeparseNodeContext context);
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt);
+static void deparseAlias(StringInfo str, Alias *alias);
+static void deparseWindowDef(StringInfo str, WindowDef* window_def);
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref);
+static void deparseSubLink(StringInfo str, SubLink* sub_link);
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context);
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr);
+static void deparseAStar(StringInfo str, A_Star* a_star);
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause);
+static void deparseSortBy(StringInfo str, SortBy* sort_by);
+static void deparseParamRef(StringInfo str, ParamRef* param_ref);
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function);
+static void deparseWithClause(StringInfo str, WithClause *with_clause);
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr);
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte);
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect);
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func);
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr * array_expr);
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr);
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context);
+static void deparseTypeName(StringInfo str, TypeName *type_name);
+static void deparseIntervalTypmods(StringInfo str, TypeName *type_name);
+static void deparseNullTest(StringInfo str, NullTest *null_test);
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr);
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when);
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection);
+static void deparseAIndices(StringInfo str, A_Indices *a_indices);
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr);
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test);
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def);
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt);
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause);
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem);
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt);
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt);
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause);
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default);
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt);
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt);
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter);
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec);
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt);
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt);
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt);
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample);
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func);
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set);
+static void deparseFuncCall(StringInfo str, FuncCall *func_call);
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr);
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr);
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize);
+static void deparseJsonIsPredicate(StringInfo str, JsonIsPredicate *json_is_predicate);
+static void deparseJsonObjectAgg(StringInfo str, JsonObjectAgg *json_object_agg);
+static void deparseJsonArrayAgg(StringInfo str, JsonArrayAgg *json_array_agg);
+static void deparseJsonObjectConstructor(StringInfo str, JsonObjectConstructor *json_object_constructor);
+static void deparseJsonArrayConstructor(StringInfo str, JsonArrayConstructor *json_array_constructor);
+static void deparseJsonArrayQueryConstructor(StringInfo str, JsonArrayQueryConstructor *json_array_query_constructor);
+static void deparseConstraint(StringInfo str, Constraint *constraint);
+static void deparseSchemaStmt(StringInfo str, Node *node);
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt);
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition);
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item);
+static void deparseAConst(StringInfo str, A_Const *a_const);
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func);
+
+static void deparsePreparableStmt(StringInfo str, Node *node);
+static void deparseRuleActionStmt(StringInfo str, Node *node);
+static void deparseExplainableStmt(StringInfo str, Node *node);
+static void deparseStmt(StringInfo str, Node *node);
+static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context);
+
+
+// "any_name" in gram.y
+static void deparseAnyName(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, parts)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipFirst(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, parts, 1)
+ {
+ Assert(IsA(lfirst(lc), String));
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+static void deparseAnyNameSkipLast(StringInfo str, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, parts)
+ {
+ if (lnext(parts, lc))
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (foreach_current_index(lc) < list_length(parts) - 2)
+ appendStringInfoChar(str, '.');
+ }
+ }
+}
+
+// "func_expr" in gram.y
+static void deparseFuncExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ case T_JsonObjectAgg:
+ deparseJsonObjectAgg(str, castNode(JsonObjectAgg, node));
+ break;
+ case T_JsonArrayAgg:
+ deparseJsonArrayAgg(str, castNode(JsonArrayAgg, node));
+ break;
+ case T_JsonObjectConstructor:
+ deparseJsonObjectConstructor(str, castNode(JsonObjectConstructor, node));
+ break;
+ case T_JsonArrayConstructor:
+ deparseJsonArrayConstructor(str, castNode(JsonArrayConstructor, node));
+ break;
+ case T_JsonArrayQueryConstructor:
+ deparseJsonArrayQueryConstructor(str, castNode(JsonArrayQueryConstructor, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in func_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+static void deparseCExpr(StringInfo str, Node *node);
+
+// "a_expr" in gram.y
+static void deparseExpr(StringInfo str, Node *node)
+{
+ if (node == NULL)
+ return;
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ case T_A_Const:
+ case T_ParamRef:
+ case T_A_Indirection:
+ case T_CaseExpr:
+ case T_SubLink:
+ case T_A_ArrayExpr:
+ case T_RowExpr:
+ case T_GroupingFunc:
+ deparseCExpr(str, node);
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_CollateClause:
+ deparseCollateClause(str, castNode(CollateClause, node));
+ break;
+ case T_A_Expr:
+ deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_BoolExpr:
+ deparseBoolExpr(str, castNode(BoolExpr, node));
+ break;
+ case T_NullTest:
+ deparseNullTest(str, castNode(NullTest, node));
+ break;
+ case T_BooleanTest:
+ deparseBooleanTest(str, castNode(BooleanTest, node));
+ break;
+ case T_JsonIsPredicate:
+ deparseJsonIsPredicate(str, castNode(JsonIsPredicate, node));
+ break;
+ case T_SetToDefault:
+ deparseSetToDefault(str, castNode(SetToDefault, node));
+ break;
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_MinMaxExpr:
+ case T_CoalesceExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ case T_JsonObjectAgg:
+ case T_JsonArrayAgg:
+ case T_JsonObjectConstructor:
+ case T_JsonArrayConstructor:
+ case T_JsonArrayQueryConstructor:
+ deparseFuncExpr(str, node);
+ break;
+ default:
+ // Note that this is also the fallthrough for deparseBExpr and deparseCExpr
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr/c_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "b_expr" in gram.y
+static void deparseBExpr(StringInfo str, Node *node)
+{
+ if (IsA(node, XmlExpr)) {
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ return;
+ }
+
+ if (IsA(node, A_Expr)) {
+ A_Expr *a_expr = castNode(A_Expr, node);
+ // Other kinds are handled by "c_expr", with parens added around them
+ if (a_expr->kind == AEXPR_OP || a_expr->kind == AEXPR_DISTINCT || a_expr->kind == AEXPR_NOT_DISTINCT) {
+ deparseAExpr(str, a_expr, DEPARSE_NODE_CONTEXT_NONE);
+ return;
+ }
+ }
+
+ if (IsA(node, BoolExpr)) {
+ BoolExpr *bool_expr = castNode(BoolExpr, node);
+ if (bool_expr->boolop == NOT_EXPR) {
+ deparseBoolExpr(str, bool_expr);
+ return;
+ }
+ }
+
+ deparseCExpr(str, node);
+}
+
+// "c_expr" in gram.y
+static void deparseCExpr(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ deparseColumnRef(str, castNode(ColumnRef, node));
+ break;
+ case T_A_Const:
+ deparseAConst(str, castNode(A_Const, node));
+ break;
+ case T_ParamRef:
+ deparseParamRef(str, castNode(ParamRef, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(str, castNode(A_Indirection, node));
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(str, castNode(CaseExpr, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(str, castNode(SubLink, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(str, castNode(RowExpr, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(str, castNode(GroupingFunc, node));
+ break;
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_MinMaxExpr:
+ case T_CoalesceExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ case T_JsonObjectAgg:
+ case T_JsonArrayAgg:
+ case T_JsonObjectConstructor:
+ case T_JsonArrayConstructor:
+ case T_JsonArrayQueryConstructor:
+ deparseFuncExpr(str, node);
+ break;
+ default:
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, node);
+ appendStringInfoChar(str, ')');
+ break;
+ }
+}
+
+// "expr_list" in gram.y
+static void deparseExprList(StringInfo str, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
+static void deparseColId(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "ColLabel", "attr_name"
+//
+// Note this is kept separate from ColId in case we ever want to be more
+// specific on how to handle keywords here
+static void deparseColLabel(StringInfo str, char *s)
+{
+ appendStringInfoString(str, quote_identifier(s));
+}
+
+// "SignedIconst" and "Iconst" in gram.y
+static void deparseSignedIconst(StringInfo str, Node *node)
+{
+ appendStringInfo(str, "%d", intVal(node));
+}
+
+// "indirection" and "opt_indirection" in gram.y
+static void deparseOptIndirection(StringInfo str, List *indirection, int N)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, indirection, N)
+ {
+ if (IsA(lfirst(lc), String))
+ {
+ appendStringInfoChar(str, '.');
+ deparseColLabel(str, strVal(lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Star))
+ {
+ appendStringInfoString(str, ".*");
+ }
+ else if (IsA(lfirst(lc), A_Indices))
+ {
+ deparseAIndices(str, castNode(A_Indices, lfirst(lc)));
+ }
+ else
+ {
+ // No other nodes should appear here
+ Assert(false);
+ }
+ }
+}
+
+// "role_list" in gram.y
+static void deparseRoleList(StringInfo str, List *roles)
+{
+ ListCell *lc;
+
+ foreach(lc, roles)
+ {
+ RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
+ deparseRoleSpec(str, role_spec);
+ if (lnext(roles, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SimpleTypename" in gram.y
+static void deparseSimpleTypename(StringInfo str, Node *node)
+{
+ deparseTypeName(str, castNode(TypeName, node));
+}
+
+// "NumericOnly" in gram.y
+static void deparseNumericOnly(StringInfo str, union ValUnion *value)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ appendStringInfo(str, "%d", value->ival.ival);
+ break;
+ case T_Float:
+ appendStringInfoString(str, value->sval.sval);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "NumericOnly_list" in gram.y
+static void deparseNumericOnlyList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseNumericOnly(str, (union ValUnion *) lfirst(lc));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "SeqOptElem" in gram.y
+static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseSimpleTypename(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cache") == 0)
+ {
+ appendStringInfoString(str, "CACHE ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NO CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "increment") == 0)
+ {
+ appendStringInfoString(str, "INCREMENT ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MAXVALUE ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MAXVALUE");
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "MINVALUE ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO MINVALUE");
+ }
+ else if (strcmp(def_elem->defname, "owned_by") == 0)
+ {
+ appendStringInfoString(str, "OWNED BY ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "sequence_name") == 0)
+ {
+ appendStringInfoString(str, "SEQUENCE NAME ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "start") == 0)
+ {
+ appendStringInfoString(str, "START ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "SeqOptList" in gram.y
+static void deparseSeqOptList(StringInfo str, List *options)
+{
+ ListCell *lc;
+ Assert(list_length(options) > 0);
+ foreach (lc, options)
+ {
+ deparseSeqOptElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "OptSeqOptList" in gram.y
+static void deparseOptSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ deparseSeqOptList(str, options);
+}
+
+// "OptParenthesizedSeqOptList" in gram.y
+static void deparseOptParenthesizedSeqOptList(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseSeqOptList(str, options);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "opt_drop_behavior" in gram.y
+static void deparseOptDropBehavior(StringInfo str, DropBehavior behavior)
+{
+ switch (behavior)
+ {
+ case DROP_RESTRICT:
+ // Default
+ break;
+ case DROP_CASCADE:
+ appendStringInfoString(str, "CASCADE ");
+ break;
+ }
+}
+
+// "any_operator" in gram.y
+static void deparseAnyOperator(StringInfo str, List *op)
+{
+ Assert(isOp(strVal(llast(op))));
+ if (list_length(op) == 2)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(linitial(op))));
+ appendStringInfoChar(str, '.');
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else if (list_length(op) == 1)
+ {
+ appendStringInfoString(str, strVal(llast(op)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "qual_Op" and "qual_all_Op" in gram.y
+static void deparseQualOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// "subquery_Op" in gram.y
+static void deparseSubqueryOp(StringInfo str, List *op)
+{
+ if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
+ {
+ appendStringInfoString(str, "LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
+ {
+ appendStringInfoString(str, "NOT LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
+ {
+ appendStringInfoString(str, "ILIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
+ {
+ appendStringInfoString(str, "NOT ILIKE");
+ }
+ else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ appendStringInfoString(str, strVal(linitial(op)));
+ }
+ else
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, op);
+ appendStringInfoString(str, ")");
+ }
+}
+
+// Not present directly in gram.y (usually matched by ColLabel)
+static void deparseGenericDefElemName(StringInfo str, const char *in)
+{
+ Assert(in != NULL);
+ char *val = pstrdup(in);
+ for (unsigned char *p = (unsigned char *) val; *p; p++)
+ *p = pg_toupper(*p);
+ appendStringInfoString(str, val);
+ pfree(val);
+}
+
+// "def_arg" and "operator_def_arg" in gram.y
+static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
+{
+ if (IsA(arg, TypeName)) // func_type
+ {
+ deparseTypeName(str, castNode(TypeName, arg));
+ }
+ else if (IsA(arg, List)) // qual_all_Op
+ {
+ List *l = castNode(List, arg);
+ Assert(list_length(l) == 1 || list_length(l) == 2);
+
+ // Schema qualified operator
+ if (list_length(l) == 2)
+ {
+ appendStringInfoString(str, "OPERATOR(");
+ deparseAnyOperator(str, l);
+ appendStringInfoChar(str, ')');
+ }
+ else if (list_length(l) == 1)
+ {
+ appendStringInfoString(str, strVal(linitial(l)));
+ }
+ }
+ else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
+ {
+ deparseValue(str, (union ValUnion *) arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (IsA(arg, String))
+ {
+ char *s = strVal(arg);
+ if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) // NONE
+ {
+ appendStringInfoString(str, "NONE");
+ }
+ else if (isReservedKeyword(s)) // reserved_keyword
+ {
+ appendStringInfoString(str, s);
+ }
+ else // Sconst
+ {
+ deparseStringLiteral(str, s);
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "definition" in gram.y
+static void deparseDefinition(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL) {
+ appendStringInfoString(str, " = ");
+ deparseDefArg(str, def_elem->arg, false);
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "opt_definition" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptDefinition(StringInfo str, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseDefinition(str, options);
+ }
+}
+
+// "create_generic_options" in gram.y
+static void deparseCreateGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ if (options == NULL)
+ return;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ")");
+}
+
+// "common_func_opt_item" in gram.y
+static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "strict") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "strict") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "CALLED ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
+ {
+ appendStringInfoString(str, "IMMUTABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
+ {
+ appendStringInfoString(str, "STABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
+ {
+ appendStringInfoString(str, "VOLATILE");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "SECURITY DEFINER");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "SECURITY INVOKER");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOT LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "cost") == 0)
+ {
+ appendStringInfoString(str, "COST ");
+ deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "rows") == 0)
+ {
+ appendStringInfoString(str, "ROWS ");
+ deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "support") == 0)
+ {
+ appendStringInfoString(str, "SUPPORT ");
+ deparseAnyName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
+ {
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "parallel") == 0)
+ {
+ appendStringInfoString(str, "PARALLEL ");
+ appendStringInfoString(str, quote_identifier(strVal(def_elem->arg)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "NonReservedWord_or_Sconst" in gram.y
+//
+// Note since both identifiers and string constants are allowed here, we
+// currently always return an identifier, except:
+//
+// 1) when the string is empty (since an empty identifier can't be scanned)
+// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
+static void deparseNonReservedWordOrSconst(StringInfo str, const char *val)
+{
+ if (strlen(val) == 0)
+ appendStringInfoString(str, "''");
+ else if (strlen(val) >= NAMEDATALEN)
+ deparseStringLiteral(str, val);
+ else
+ appendStringInfoString(str, quote_identifier(val));
+}
+
+// "func_as" in gram.y
+static void deparseFuncAs(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ char *strval = strVal(lfirst(lc));
+ if (strstr(strval, "$$") == NULL)
+ {
+ appendStringInfoString(str, "$$");
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, "$$");
+ }
+ else
+ {
+ deparseStringLiteral(str, strval);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createfunc_opt_item" in gram.y
+static void deparseCreateFuncOptItem(StringInfo str, DefElem *def_elem)
+{
+ ListCell *lc = NULL;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseFuncAs(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "transform") == 0)
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, "TRANSFORM ");
+ foreach (lc, l)
+ {
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ else if (strcmp(def_elem->defname, "window") == 0)
+ {
+ appendStringInfoString(str, "WINDOW");
+ }
+ else
+ {
+ deparseCommonFuncOptItem(str, def_elem);
+ }
+}
+
+// "alter_generic_options" in gram.y
+static void deparseAlterGenericOptions(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ switch (def_elem->defaction)
+ {
+ case DEFELEM_UNSPEC:
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_SET:
+ appendStringInfoString(str, "SET ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_ADD:
+ appendStringInfoString(str, "ADD ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoChar(str, ' ');
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ break;
+ case DEFELEM_DROP:
+ appendStringInfoString(str, "DROP ");
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ break;
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+}
+
+// "func_name" in gram.y
+static void deparseFuncName(StringInfo str, List *func_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, func_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(func_name, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "function_with_argtypes" in gram.y
+static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc;
+ deparseFuncName(str, object_with_args->objname);
+
+ if (!object_with_args->args_unspecified)
+ {
+ appendStringInfoChar(str, '(');
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+// "function_with_argtypes_list" in gram.y
+static void deparseFunctionWithArgtypesList(StringInfo str, List *l)
+{
+ ListCell *lc;
+
+ foreach(lc, l)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "operator_with_argtypes" in gram.y
+static void deparseOperatorWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ deparseAnyOperator(str, object_with_args->objname);
+
+ Assert(list_length(object_with_args->objargs) == 2);
+ appendStringInfoChar(str, '(');
+ if (linitial(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, linitial(object_with_args->objargs)));
+ appendStringInfoString(str, ", ");
+ if (lsecond(object_with_args->objargs) == NULL)
+ appendStringInfoString(str, "NONE");
+ else
+ deparseTypeName(str, castNode(TypeName, lsecond(object_with_args->objargs)));
+ appendStringInfoChar(str, ')');
+}
+
+// "aggr_args" in gram.y
+static void deparseAggrArgs(StringInfo str, List *aggr_args)
+{
+ Assert(list_length(aggr_args) == 2);
+
+ ListCell *lc = NULL;
+ List *args = linitial(aggr_args);
+ int order_by_pos = intVal(lsecond(aggr_args));
+
+ appendStringInfoChar(str, '(');
+ if (args == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ foreach(lc, args)
+ {
+ if (foreach_current_index(lc) == order_by_pos)
+ {
+ if (foreach_current_index(lc) > 0)
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, "ORDER BY ");
+ }
+ else if (foreach_current_index(lc) > 0)
+ {
+ appendStringInfoString(str, ", ");
+ }
+
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ }
+
+ // Repeat the last direct arg as a ordered arg to handle the
+ // simplification done by makeOrderedSetArgs in gram.y
+ if (order_by_pos == list_length(args))
+ {
+ appendStringInfoString(str, " ORDER BY ");
+ deparseFunctionParameter(str, castNode(FunctionParameter, llast(args)));
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "aggregate_with_argtypes" in gram.y
+static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc = NULL;
+
+ deparseFuncName(str, object_with_args->objname);
+
+ appendStringInfoChar(str, '(');
+ if (object_with_args->objargs == NULL && object_with_args->objfuncargs == NULL)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else
+ {
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "columnList" in gram.y
+static void deparseColumnList(StringInfo str, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(columns, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptTemp" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptTemp(StringInfo str, char relpersistence)
+{
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_PERMANENT:
+ // Default
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ appendStringInfoString(str, "UNLOGGED ");
+ break;
+ case RELPERSISTENCE_TEMP:
+ appendStringInfoString(str, "TEMPORARY ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+// "relation_expr_list" in gram.y
+static void deparseRelationExprList(StringInfo str, List *relation_exprs)
+{
+ ListCell *lc = NULL;
+ foreach(lc, relation_exprs)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(relation_exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "handler_name" in gram.y
+static void deparseHandlerName(StringInfo str, List *handler_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, handler_name)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(handler_name, lc))
+ appendStringInfoChar(str, '.');
+ }
+}
+
+// "fdw_options" in gram.y
+static void deparseFdwOptions(StringInfo str, List *fdw_options)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, fdw_options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO HANDLER ");
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NO VALIDATOR ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(fdw_options, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "type_list" in gram.y
+static void deparseTypeList(StringInfo str, List *type_list)
+{
+ ListCell *lc = NULL;
+ foreach(lc, type_list)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(type_list, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_boolean_or_string" in gram.y
+static void deparseOptBooleanOrString(StringInfo str, char *s)
+{
+ if (s == NULL)
+ return; // No value set
+ else if (strcmp(s, "true") == 0)
+ appendStringInfoString(str, "TRUE");
+ else if (strcmp(s, "false") == 0)
+ appendStringInfoString(str, "FALSE");
+ else if (strcmp(s, "on") == 0)
+ appendStringInfoString(str, "ON");
+ else if (strcmp(s, "off") == 0)
+ appendStringInfoString(str, "OFF");
+ else
+ deparseNonReservedWordOrSconst(str, s);
+}
+
+static void deparseOptBoolean(StringInfo str, Node *node)
+{
+ if (node == NULL)
+ {
+ return;
+ }
+
+ switch (nodeTag(node))
+ {
+ case T_String:
+ appendStringInfo(str, " %s", strVal(node));
+ break;
+ case T_Integer:
+ appendStringInfo(str, " %d", intVal(node));
+ break;
+ case T_Boolean:
+ appendStringInfo(str, " %s", boolVal(node) ? "TRUE" : "FALSE");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+bool optBooleanValue(Node *node)
+{
+ if (node == NULL)
+ {
+ return true;
+ }
+
+ switch (nodeTag(node))
+ {
+ case T_String: {
+ // Longest valid string is "off\0"
+ char lower[4];
+ strncpy(lower, strVal(node), 4);
+ lower[3] = 0;
+
+ if (strcmp(lower, "on") == 0) {
+ return true;
+ } else if (strcmp(lower, "off") == 0) {
+ return false;
+ }
+
+ // No sane way to handle this.
+ return false;
+ }
+ case T_Integer:
+ return intVal(node) != 0;
+ case T_Boolean:
+ return boolVal(node);
+ default:
+ Assert(false);
+ return false;
+ }
+}
+
+// "var_name"
+//
+// Note this is kept separate from ColId in case we want to improve the
+// output of namespaced variable names
+static void deparseVarName(StringInfo str, char *s)
+{
+ deparseColId(str, s);
+}
+
+// "var_list"
+static void deparseVarList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, lfirst(lc));
+ if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
+ deparseNumericOnly(str, (union ValUnion *) &a_const->val);
+ else if (IsA(&a_const->val, String))
+ deparseOptBooleanOrString(str, strVal(&a_const->val));
+ else
+ Assert(false);
+ }
+ else if (IsA(lfirst(lc), TypeCast))
+ {
+ deparseTypeCast(str, castNode(TypeCast, lfirst(lc)), DEPARSE_NODE_CONTEXT_SET_STATEMENT);
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "transaction_mode_list" in gram.y
+static void deparseTransactionModeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "transaction_isolation") == 0)
+ {
+ char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
+ appendStringInfoString(str, "ISOLATION LEVEL ");
+ if (strcmp(s, "read uncommitted") == 0)
+ appendStringInfoString(str, "READ UNCOMMITTED");
+ else if (strcmp(s, "read committed") == 0)
+ appendStringInfoString(str, "READ COMMITTED");
+ else if (strcmp(s, "repeatable read") == 0)
+ appendStringInfoString(str, "REPEATABLE READ");
+ else if (strcmp(s, "serializable") == 0)
+ appendStringInfoString(str, "SERIALIZABLE");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "READ ONLY");
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "READ WRITE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ appendStringInfoString(str, "DEFERRABLE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ appendStringInfoString(str, "NOT DEFERRABLE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "alter_identity_column_option_list" in gram.y
+static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ appendStringInfoString(str, "RESTART ");
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "generated") == 0)
+ {
+ appendStringInfoString(str, "SET GENERATED ");
+ if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
+ appendStringInfoString(str, "ALWAYS");
+ else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+ appendStringInfoString(str, "BY DEFAULT");
+ else
+ Assert(false);
+ }
+ else
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSeqOptElem(str, def_elem);
+ }
+ if (lnext(l, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "reloptions" in gram.y
+static void deparseRelOptions(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (def_elem->defnamespace != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defnamespace));
+ appendStringInfoChar(str, '.');
+ }
+ if (def_elem->defname != NULL)
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->defname != NULL && def_elem->arg != NULL)
+ appendStringInfoChar(str, '=');
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, false);
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+// "OptWith" and "opt_reloptions" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptWith(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "WITH ");
+ deparseRelOptions(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "target_list" and "opt_target_list" in gram.y
+static void deparseTargetList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+
+ if (res_target->val == NULL)
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
+ else if (IsA(res_target->val, ColumnRef))
+ deparseColumnRef(str, castNode(ColumnRef, res_target->val));
+ else
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL) {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "insert_column_list" in gram.y
+static void deparseInsertColumnList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->name != NULL);
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ deparseOptIndirection(str, res_target->indirection, 0);
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_attribute_list" in gram.y
+static void deparseXmlAttributeList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "xml_namespace_list" in gram.y
+static void deparseXmlNamespaceList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (res_target->name == NULL)
+ appendStringInfoString(str, "DEFAULT ");
+
+ deparseExpr(str, res_target->val);
+
+ if (res_target->name != NULL)
+ {
+ appendStringInfoString(str, " AS ");
+ appendStringInfoString(str, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "table_ref" in gram.y
+static void deparseTableRef(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_RangeVar:
+ deparseRangeVar(str, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_RangeTableSample:
+ deparseRangeTableSample(str, castNode(RangeTableSample, node));
+ break;
+ case T_RangeFunction:
+ deparseRangeFunction(str, castNode(RangeFunction, node));
+ break;
+ case T_RangeTableFunc:
+ deparseRangeTableFunc(str, castNode(RangeTableFunc, node));
+ break;
+ case T_RangeSubselect:
+ deparseRangeSubselect(str, castNode(RangeSubselect, node));
+ break;
+ case T_JoinExpr:
+ deparseJoinExpr(str, castNode(JoinExpr, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "from_list" in gram.y
+static void deparseFromList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseTableRef(str, lfirst(lc));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "from_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseFromClause(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseFromList(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "where_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereClause(StringInfo str, Node *node)
+{
+ if (node != NULL)
+ {
+ appendStringInfoString(str, "WHERE ");
+ deparseExpr(str, node);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "where_or_current_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereOrCurrentClause(StringInfo str, Node *node)
+{
+ if (node == NULL)
+ return;
+
+ appendStringInfoString(str, "WHERE ");
+
+ if (IsA(node, CurrentOfExpr)) {
+ CurrentOfExpr *current_of_expr = castNode(CurrentOfExpr, node);
+ appendStringInfoString(str, "CURRENT OF ");
+ appendStringInfoString(str, quote_identifier(current_of_expr->cursor_name));
+ } else {
+ deparseExpr(str, node);
+ }
+
+ appendStringInfoChar(str, ' ');
+}
+
+// "group_by_list" in gram.y
+static void deparseGroupByList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), GroupingSet))
+ deparseGroupingSet(str, castNode(GroupingSet, lfirst(lc)));
+ else
+ deparseExpr(str, lfirst(lc));
+
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "set_target" in gram.y
+static void deparseSetTarget(StringInfo str, ResTarget *res_target)
+{
+ Assert(res_target->name != NULL);
+ deparseColId(str, res_target->name);
+ deparseOptIndirection(str, res_target->indirection, 0);
+}
+
+// "any_name_list" in gram.y
+static void deparseAnyNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseAnyName(str, castNode(List, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "name_list" in gram.y
+static void deparseNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseColId(str, strVal(lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "opt_sort_clause" and "json_array_aggregate_order_by_clause_opt" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptSortClause(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "ORDER BY ");
+
+ foreach(lc, l)
+ {
+ deparseSortBy(str, castNode(SortBy, lfirst(lc)));
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "func_arg_expr" in gram.y
+static void deparseFuncArgExpr(StringInfo str, Node *node)
+{
+ if (IsA(node, NamedArgExpr))
+ {
+ NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
+ appendStringInfoString(str, named_arg_expr->name);
+ appendStringInfoString(str, " := ");
+ deparseExpr(str, (Node *) named_arg_expr->arg);
+ }
+ else
+ {
+ deparseExpr(str, node);
+ }
+}
+
+// "set_clause_list" in gram.y
+static void deparseSetClauseList(StringInfo str, List *target_list)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ int skip_next_n_elems = 0;
+
+ Assert(list_length(target_list) > 0);
+
+ foreach(lc, target_list)
+ {
+ if (skip_next_n_elems > 0)
+ {
+ skip_next_n_elems--;
+ continue;
+ }
+
+ if (foreach_current_index(lc) != 0)
+ appendStringInfoString(str, ", ");
+
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (IsA(res_target->val, MultiAssignRef))
+ {
+ MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
+ appendStringInfoString(str, "(");
+ for_each_cell(lc2, target_list, lc)
+ {
+ deparseSetTarget(str, castNode(ResTarget, lfirst(lc2)));
+ if (foreach_current_index(lc2) == r->ncolumns - 1) // Last element in this multi-assign
+ break;
+ else if (lnext(target_list, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") = ");
+ deparseExpr(str, r->source);
+ skip_next_n_elems = r->ncolumns - 1;
+ }
+ else
+ {
+ deparseSetTarget(str, res_target);
+ appendStringInfoString(str, " = ");
+ deparseExpr(str, res_target->val);
+ }
+ }
+}
+
+// "func_expr_windowless" in gram.y
+static void deparseFuncExprWindowless(StringInfo str, Node* node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(str, castNode(FuncCall, node));
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_FUNC_EXPR);
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(str, castNode(XmlExpr, node));
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(str, castNode(XmlSerialize, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "opt_collate" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptCollate(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, l);
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "index_elem" in gram.y
+static void deparseIndexElem(StringInfo str, IndexElem* index_elem)
+{
+ if (index_elem->name != NULL)
+ {
+ deparseColId(str, index_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (index_elem->expr != NULL)
+ {
+ switch (nodeTag(index_elem->expr))
+ {
+ // Simple function calls can be written without wrapping parens
+ case T_FuncCall: // func_application
+ case T_SQLValueFunction: // func_expr_common_subexpr
+ case T_CoalesceExpr: // func_expr_common_subexpr
+ case T_MinMaxExpr: // func_expr_common_subexpr
+ case T_XmlExpr: // func_expr_common_subexpr
+ case T_XmlSerialize: // func_expr_common_subexpr
+ deparseFuncExprWindowless(str, index_elem->expr);
+ appendStringInfoString(str, " ");
+ break;
+ default:
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, index_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseOptCollate(str, index_elem->collation);
+
+ if (list_length(index_elem->opclass) > 0)
+ {
+ deparseAnyName(str, index_elem->opclass);
+
+ if (list_length(index_elem->opclassopts) > 0)
+ deparseRelOptions(str, index_elem->opclassopts);
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (index_elem->ordering)
+ {
+ case SORTBY_DEFAULT:
+ // Default
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ // Not allowed in CREATE INDEX
+ Assert(false);
+ break;
+ }
+
+ switch (index_elem->nulls_ordering)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ // Default
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+// "qualified_name_list" in gram.y
+static void deparseQualifiedNameList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(l, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "OptInherit" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptInherit(StringInfo str, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ appendStringInfoString(str, "INHERITS (");
+ deparseQualifiedNameList(str, l);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+// "privilege_target" in gram.y
+static void deparsePrivilegeTarget(StringInfo str, GrantTargetType targtype, ObjectType objtype, List *objs)
+{
+ switch (targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseQualifiedNameList(str, objs);
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "FOREIGN SERVER ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypesList(str, objs);
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyNameList(str, objs);
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnlyList(str, objs);
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "ALL TABLES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "ALL SEQUENCES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "ALL FUNCTIONS IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "ALL PROCEDURES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ALL ROUTINES IN SCHEMA ");
+ deparseNameList(str, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_DEFAULTS: // defacl_privilege_target
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLES");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTIONS");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPES");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMAS");
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ }
+}
+
+// "opclass_item_list" in gram.y
+static void deparseOpclassItemList(StringInfo str, List *items)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, items)
+ {
+ deparseCreateOpClassItem(str, castNode(CreateOpClassItem, lfirst(lc)));
+ if (lnext(items, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+// "createdb_opt_list" in gram.y
+static void deparseCreatedbOptList(StringInfo str, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "connection_limit") == 0)
+ appendStringInfoString(str, "CONNECTION LIMIT");
+ else
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ appendStringInfoString(str, "DEFAULT");
+ else if (IsA(def_elem->arg, Integer))
+ deparseSignedIconst(str, def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+
+ if (lnext(l, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+// "utility_option_list" in gram.y
+static void deparseUtilityOptionList(StringInfo str, List *options)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ if (list_length(options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(str, def_elem->defname);
+
+ if (def_elem->arg != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ else
+ Assert(false);
+ }
+
+ if (lnext(options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
+{
+ const ListCell *lc = NULL;
+ const ListCell *lc2 = NULL;
+
+ if (stmt->withClause)
+ {
+ deparseWithClause(str, stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (stmt->op) {
+ case SETOP_NONE:
+ if (list_length(stmt->valuesLists) > 0)
+ {
+ const ListCell *lc;
+ appendStringInfoString(str, "VALUES ");
+
+ foreach(lc, stmt->valuesLists)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, lfirst(lc));
+ appendStringInfoChar(str, ')');
+ if (lnext(stmt->valuesLists, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ }
+
+ appendStringInfoString(str, "SELECT ");
+
+ if (list_length(stmt->targetList) > 0)
+ {
+ if (stmt->distinctClause != NULL)
+ {
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
+ {
+ appendStringInfoString(str, "ON (");
+ deparseExprList(str, stmt->distinctClause);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ deparseTargetList(str, stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->intoClause != NULL)
+ {
+ appendStringInfoString(str, "INTO ");
+ deparseOptTemp(str, stmt->intoClause->rel->relpersistence);
+ deparseIntoClause(str, stmt->intoClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, stmt->fromClause);
+ deparseWhereClause(str, stmt->whereClause);
+
+ if (list_length(stmt->groupClause) > 0)
+ {
+ appendStringInfoString(str, "GROUP BY ");
+ if (stmt->groupDistinct)
+ appendStringInfoString(str, "DISTINCT ");
+ deparseGroupByList(str, stmt->groupClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->havingClause != NULL)
+ {
+ appendStringInfoString(str, "HAVING ");
+ deparseExpr(str, stmt->havingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (stmt->windowClause != NULL)
+ {
+ appendStringInfoString(str, "WINDOW ");
+ foreach(lc, stmt->windowClause)
+ {
+ WindowDef *window_def = castNode(WindowDef, lfirst(lc));
+ Assert(window_def->name != NULL);
+ appendStringInfoString(str, window_def->name);
+ appendStringInfoString(str, " AS ");
+ deparseWindowDef(str, window_def);
+ if (lnext(stmt->windowClause, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case SETOP_UNION:
+ case SETOP_INTERSECT:
+ case SETOP_EXCEPT:
+ {
+ bool need_larg_parens =
+ list_length(stmt->larg->sortClause) > 0 ||
+ stmt->larg->limitOffset != NULL ||
+ stmt->larg->limitCount != NULL ||
+ list_length(stmt->larg->lockingClause) > 0 ||
+ stmt->larg->withClause != NULL ||
+ stmt->larg->op != SETOP_NONE;
+ bool need_rarg_parens =
+ list_length(stmt->rarg->sortClause) > 0 ||
+ stmt->rarg->limitOffset != NULL ||
+ stmt->rarg->limitCount != NULL ||
+ list_length(stmt->rarg->lockingClause) > 0 ||
+ stmt->rarg->withClause != NULL ||
+ stmt->rarg->op != SETOP_NONE;
+ if (need_larg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->larg);
+ if (need_larg_parens)
+ appendStringInfoChar(str, ')');
+ switch (stmt->op)
+ {
+ case SETOP_UNION:
+ appendStringInfoString(str, " UNION ");
+ break;
+ case SETOP_INTERSECT:
+ appendStringInfoString(str, " INTERSECT ");
+ break;
+ case SETOP_EXCEPT:
+ appendStringInfoString(str, " EXCEPT ");
+ break;
+ default:
+ Assert(false);
+ }
+ if (stmt->all)
+ appendStringInfoString(str, "ALL ");
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, stmt->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ }
+
+ deparseOptSortClause(str, stmt->sortClause);
+
+ if (stmt->limitCount != NULL)
+ {
+ if (stmt->limitOption == LIMIT_OPTION_COUNT)
+ appendStringInfoString(str, "LIMIT ");
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ appendStringInfoString(str, "FETCH FIRST ");
+
+ if (IsA(stmt->limitCount, A_Const) && castNode(A_Const, stmt->limitCount)->isnull)
+ appendStringInfoString(str, "ALL");
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ deparseCExpr(str, stmt->limitCount);
+ else
+ deparseExpr(str, stmt->limitCount);
+
+ appendStringInfoChar(str, ' ');
+
+ if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ appendStringInfoString(str, "ROWS WITH TIES ");
+ }
+
+ if (stmt->limitOffset != NULL)
+ {
+ appendStringInfoString(str, "OFFSET ");
+ deparseExpr(str, stmt->limitOffset);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(stmt->lockingClause) > 0)
+ {
+ foreach(lc, stmt->lockingClause)
+ {
+ deparseLockingClause(str, castNode(LockingClause, lfirst(lc)));
+ if (lnext(stmt->lockingClause, lc))
+ appendStringInfoString(str, " ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseIntoClause(StringInfo str, IntoClause *into_clause)
+{
+ ListCell *lc;
+
+ deparseRangeVar(str, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE); /* target relation name */
+
+ if (list_length(into_clause->colNames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, into_clause->colNames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (into_clause->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(into_clause->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptWith(str, into_clause->options);
+
+ switch (into_clause->onCommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (into_clause->tableSpaceName != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(into_clause->tableSpaceName));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context)
+{
+ if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ONLY ");
+
+ if (range_var->catalogname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->catalogname));
+ appendStringInfoChar(str, '.');
+ }
+
+ if (range_var->schemaname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(range_var->schemaname));
+ appendStringInfoChar(str, '.');
+ }
+
+ Assert(range_var->relname != NULL);
+ appendStringInfoString(str, quote_identifier(range_var->relname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_var->alias != NULL)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_var->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+void deparseRawStmt(StringInfo str, RawStmt *raw_stmt)
+{
+ if (raw_stmt->stmt == NULL)
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
+
+ deparseStmt(str, raw_stmt->stmt);
+}
+
+static void deparseAlias(StringInfo str, Alias *alias)
+{
+ appendStringInfoString(str, quote_identifier(alias->aliasname));
+
+ if (list_length(alias->colnames) > 0)
+ {
+ const ListCell *lc = NULL;
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, alias->colnames);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseAConst(StringInfo str, A_Const *a_const)
+{
+ union ValUnion *val = a_const->isnull ? NULL : &a_const->val;
+ deparseValue(str, val, DEPARSE_NODE_CONTEXT_CONSTANT);
+}
+
+static void deparseFuncCall(StringInfo str, FuncCall *func_call)
+{
+ const ListCell *lc = NULL;
+
+ Assert(list_length(func_call->funcname) > 0);
+
+ if (list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "OVERLAY(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PLACING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "substring") == 0)
+ {
+ /*
+ * "SUBSTRING" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.substring)
+ */
+ Assert(list_length(func_call->args) == 2 || list_length(func_call->args) == 3);
+ appendStringInfoString(str, "SUBSTRING(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lsecond(func_call->args));
+ if (list_length(func_call->args) == 3)
+ {
+ appendStringInfoString(str, " FOR ");
+ deparseExpr(str, lthird(func_call->args));
+ }
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "position") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "POSITION" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.position)
+ * Note that the first and second arguments are switched in this format
+ */
+ appendStringInfoString(str, "POSITION(");
+ deparseBExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " IN ");
+ deparseBExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 3)
+ {
+ /*
+ * "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "overlay(");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " placing ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " from ");
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "pg_collation_for") == 0 &&
+ list_length(func_call->args) == 1)
+ {
+ /*
+ * "collation for" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ appendStringInfoString(str, "collation for (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "extract") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "EXTRACT" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.extract)
+ */
+ appendStringInfoString(str, "extract (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlaps") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * "OVERLAPS" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlaps)
+ * format: (start_1, end_1) overlaps (start_2, end_2)
+ */
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, ") ");
+
+ appendStringInfoString(str, "overlaps ");
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, lthird(func_call->args));
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, lfourth(func_call->args));
+ appendStringInfoString(str, ") ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ (
+ strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0
+ ))
+ {
+ /*
+ * "TRIM " is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.ltrim)
+ * Note that the first and second arguments are switched in this format
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ appendStringInfoString(str, "TRIM (");
+ if (strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0)
+ appendStringInfoString(str, "LEADING ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0)
+ appendStringInfoString(str, "BOTH ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0)
+ appendStringInfoString(str, "TRAILING ");
+
+ if (list_length(func_call->args) == 2)
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoString(str, " FROM ");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "timezone") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "AT TIME ZONE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.timezone)
+ * Note that the arguments are swapped in this case
+ */
+ Expr* e = lsecond(func_call->args);
+
+ if (IsA(e, A_Expr)) {
+ appendStringInfoChar(str, '(');
+ }
+
+ deparseExpr(str, (Node*) e);
+
+ if (IsA(e, A_Expr)) {
+ appendStringInfoChar(str, ')');
+ }
+
+ appendStringInfoString(str, " AT TIME ZONE ");
+ deparseExpr(str, linitial(func_call->args));
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "normalize") == 0)
+ {
+ /*
+ * "NORMALIZE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.normalize)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ appendStringInfoString(str, "normalize (");
+
+ deparseExpr(str, linitial(func_call->args));
+ if (list_length(func_call->args) == 2)
+ {
+ appendStringInfoString(str, ", ");
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "is_normalized") == 0)
+ {
+ /*
+ * "IS NORMALIZED" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.is_normalized)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " IS ");
+ if (list_length(func_call->args) == 2)
+ {
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ appendStringInfoString(str, " NORMALIZED ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "xmlexists") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ appendStringInfoString(str, "xmlexists (");
+ deparseExpr(str, linitial(func_call->args));
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, lsecond(func_call->args));
+ appendStringInfoChar(str, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "system_user") == 0)
+ {
+ appendStringInfoString(str, "SYSTEM_USER");
+ return;
+ }
+
+ deparseFuncName(str, func_call->funcname);
+ appendStringInfoChar(str, '(');
+
+ if (func_call->agg_distinct)
+ appendStringInfoString(str, "DISTINCT ");
+
+ if (func_call->agg_star)
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (list_length(func_call->args) > 0)
+ {
+ foreach(lc, func_call->args)
+ {
+ if (func_call->func_variadic && !lnext(func_call->args, lc))
+ appendStringInfoString(str, "VARIADIC ");
+ deparseFuncArgExpr(str, lfirst(lc));
+ if (lnext(func_call->args, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (func_call->agg_order != NULL && !func_call->agg_within_group)
+ {
+ deparseOptSortClause(str, func_call->agg_order);
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+
+ if (func_call->agg_order != NULL && func_call->agg_within_group)
+ {
+ appendStringInfoString(str, "WITHIN GROUP (");
+ deparseOptSortClause(str, func_call->agg_order);
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->agg_filter)
+ {
+ appendStringInfoString(str, "FILTER (WHERE ");
+ deparseExpr(str, func_call->agg_filter);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (func_call->over)
+ {
+ appendStringInfoString(str, "OVER ");
+ if (func_call->over->name)
+ appendStringInfoString(str, func_call->over->name);
+ else
+ deparseWindowDef(str, func_call->over);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseWindowDef(StringInfo str, WindowDef* window_def)
+{
+ ListCell *lc;
+
+ // The parent node is responsible for outputting window_def->name
+
+ appendStringInfoChar(str, '(');
+
+ if (window_def->refname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(window_def->refname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(window_def->partitionClause) > 0)
+ {
+ appendStringInfoString(str, "PARTITION BY ");
+ deparseExprList(str, window_def->partitionClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseOptSortClause(str, window_def->orderClause);
+
+ if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
+ {
+ if (window_def->frameOptions & FRAMEOPTION_RANGE)
+ appendStringInfoString(str, "RANGE ");
+ else if (window_def->frameOptions & FRAMEOPTION_ROWS)
+ appendStringInfoString(str, "ROWS ");
+ else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
+ appendStringInfoString(str, "GROUPS ");
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ appendStringInfoString(str, "BETWEEN ");
+
+ // frame_start
+ if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ {
+ appendStringInfoString(str, "UNBOUNDED PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(str, window_def->startOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ {
+ appendStringInfoString(str, "AND ");
+
+ // frame_end
+ if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
+ {
+ appendStringInfoString(str, "UNBOUNDED FOLLOWING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
+ {
+ appendStringInfoString(str, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(str, window_def->endOffset);
+ appendStringInfoString(str, " FOLLOWING ");
+ }
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
+ appendStringInfoString(str, "EXCLUDE CURRENT ROW ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
+ appendStringInfoString(str, "EXCLUDE GROUP ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
+ appendStringInfoString(str, "EXCLUDE TIES ");
+ }
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseColumnRef(StringInfo str, ColumnRef* column_ref)
+{
+ Assert(list_length(column_ref->fields) >= 1);
+
+ if (IsA(linitial(column_ref->fields), A_Star))
+ deparseAStar(str, castNode(A_Star, linitial(column_ref->fields)));
+ else if (IsA(linitial(column_ref->fields), String))
+ deparseColLabel(str, strVal(linitial(column_ref->fields)));
+
+ deparseOptIndirection(str, column_ref->fields, 1);
+}
+
+static void deparseSubLink(StringInfo str, SubLink* sub_link)
+{
+ switch (sub_link->subLinkType) {
+ case EXISTS_SUBLINK:
+ appendStringInfoString(str, "EXISTS (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ALL_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ALL (");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ANY_SUBLINK:
+ deparseExpr(str, sub_link->testexpr);
+ if (list_length(sub_link->operName) > 0)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, sub_link->operName);
+ appendStringInfoString(str, " ANY ");
+ }
+ else
+ {
+ appendStringInfoString(str, " IN ");
+ }
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case ROWCOMPARE_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case EXPR_SUBLINK:
+ appendStringInfoString(str, "(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case MULTIEXPR_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case ARRAY_SUBLINK:
+ appendStringInfoString(str, "ARRAY(");
+ deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
+ appendStringInfoChar(str, ')');
+ return;
+ case CTE_SUBLINK: /* for SubPlans only */
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ }
+}
+
+static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context)
+{
+ ListCell *lc;
+ char *name;
+
+ bool need_lexpr_parens = a_expr->lexpr != NULL && (IsA(a_expr->lexpr, BoolExpr) || IsA(a_expr->lexpr, BooleanTest) || IsA(a_expr->lexpr, NullTest) || IsA(a_expr->lexpr, A_Expr));
+ bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, BooleanTest) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
+
+ switch (a_expr->kind) {
+ case AEXPR_OP: /* normal operator */
+ {
+ bool need_outer_parens = context == DEPARSE_NODE_CONTEXT_A_EXPR;
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, '(');
+ if (a_expr->lexpr != NULL)
+ {
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ deparseQualOp(str, a_expr->name);
+ if (a_expr->rexpr != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ }
+
+ if (need_outer_parens)
+ appendStringInfoChar(str, ')');
+ }
+ return;
+ case AEXPR_OP_ANY: /* scalar op ANY (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ANY(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_OP_ALL: /* scalar op ALL (array) */
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ deparseSubqueryOp(str, a_expr->name);
+ appendStringInfoString(str, " ALL(");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->lexpr);
+ if (need_lexpr_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoString(str, " IS DISTINCT FROM ");
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, a_expr->rexpr);
+ if (need_rexpr_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, " IS NOT DISTINCT FROM ");
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_NULLIF: /* NULLIF - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ appendStringInfoString(str, "NULLIF(");
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, a_expr->rexpr);
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "=") == 0) {
+ appendStringInfoString(str, "IN ");
+ } else if (strcmp(name, "<>") == 0) {
+ appendStringInfoString(str, "NOT IN ");
+ } else {
+ Assert(false);
+ }
+ appendStringInfoChar(str, '(');
+ if (IsA(a_expr->rexpr, SubLink))
+ deparseSubLink(str, castNode(SubLink, a_expr->rexpr));
+ else
+ deparseExprList(str, castNode(List, a_expr->rexpr));
+ appendStringInfoChar(str, ')');
+ return;
+ case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~~") == 0) {
+ appendStringInfoString(str, "LIKE ");
+ } else if (strcmp(name, "!~~") == 0) {
+ appendStringInfoString(str, "NOT LIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~~*") == 0) {
+ appendStringInfoString(str, "ILIKE ");
+ } else if (strcmp(name, "!~~*") == 0) {
+ appendStringInfoString(str, "NOT ILIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(str, a_expr->rexpr);
+ return;
+ case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~") == 0) {
+ appendStringInfoString(str, "SIMILAR TO ");
+ } else if (strcmp(name, "!~") == 0) {
+ appendStringInfoString(str, "NOT SIMILAR TO ");
+ } else {
+ Assert(false);
+ }
+
+ FuncCall *n = castNode(FuncCall, a_expr->rexpr);
+ Assert(list_length(n->funcname) == 2);
+ Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
+ Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
+ Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
+
+ deparseExpr(str, linitial(n->args));
+ if (list_length(n->args) == 2)
+ {
+ appendStringInfoString(str, " ESCAPE ");
+ deparseExpr(str, lsecond(n->args));
+ }
+
+ return;
+ case AEXPR_BETWEEN: /* name must be "BETWEEN" */
+ case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
+ case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
+ case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+
+ deparseExpr(str, a_expr->lexpr);
+ appendStringInfoChar(str, ' ');
+ appendStringInfoString(str, strVal(linitial(a_expr->name)));
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, castNode(List, a_expr->rexpr)) {
+ deparseExpr(str, lfirst(lc));
+ if (lnext(castNode(List, a_expr->rexpr), lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ }
+}
+
+static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr)
+{
+ const ListCell *lc = NULL;
+ switch (bool_expr->boolop)
+ {
+ case AND_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(bool_expr->args, lc))
+ appendStringInfoString(str, " AND ");
+ }
+ return;
+ case OR_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, lfirst(lc));
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ if (lnext(bool_expr->args, lc))
+ appendStringInfoString(str, " OR ");
+ }
+ return;
+ case NOT_EXPR:
+ Assert(list_length(bool_expr->args) == 1);
+ bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
+ appendStringInfoString(str, "NOT ");
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, linitial(bool_expr->args));
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ return;
+ }
+}
+
+static void deparseAStar(StringInfo str, A_Star *a_star)
+{
+ appendStringInfoChar(str, '*');
+}
+
+static void deparseCollateClause(StringInfo str, CollateClause* collate_clause)
+{
+ ListCell *lc;
+ if (collate_clause->arg != NULL)
+ {
+ bool need_parens = IsA(collate_clause->arg, A_Expr);
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, collate_clause->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoString(str, "COLLATE ");
+ deparseAnyName(str, collate_clause->collname);
+}
+
+static void deparseSortBy(StringInfo str, SortBy* sort_by)
+{
+ deparseExpr(str, sort_by->node);
+ appendStringInfoChar(str, ' ');
+
+ switch (sort_by->sortby_dir)
+ {
+ case SORTBY_DEFAULT:
+ break;
+ case SORTBY_ASC:
+ appendStringInfoString(str, "ASC ");
+ break;
+ case SORTBY_DESC:
+ appendStringInfoString(str, "DESC ");
+ break;
+ case SORTBY_USING:
+ appendStringInfoString(str, "USING ");
+ deparseQualOp(str, sort_by->useOp);
+ break;
+ }
+
+ switch (sort_by->sortby_nulls)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ break;
+ case SORTBY_NULLS_FIRST:
+ appendStringInfoString(str, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ appendStringInfoString(str, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseParamRef(StringInfo str, ParamRef* param_ref)
+{
+ if (param_ref->number == 0) {
+ appendStringInfoChar(str, '?');
+ } else {
+ appendStringInfo(str, "$%d", param_ref->number);
+ }
+}
+
+static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function)
+{
+ switch (sql_value_function->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ appendStringInfoString(str, "current_date");
+ break;
+ case SVFOP_CURRENT_TIME:
+ appendStringInfoString(str, "current_time");
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ appendStringInfoString(str, "current_time"); // with precision
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ appendStringInfoString(str, "current_timestamp");
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ appendStringInfoString(str, "current_timestamp"); // with precision
+ break;
+ case SVFOP_LOCALTIME:
+ appendStringInfoString(str, "localtime");
+ break;
+ case SVFOP_LOCALTIME_N:
+ appendStringInfoString(str, "localtime"); // with precision
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ appendStringInfoString(str, "localtimestamp");
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ appendStringInfoString(str, "localtimestamp"); // with precision
+ break;
+ case SVFOP_CURRENT_ROLE:
+ appendStringInfoString(str, "current_role");
+ break;
+ case SVFOP_CURRENT_USER:
+ appendStringInfoString(str, "current_user");
+ break;
+ case SVFOP_USER:
+ appendStringInfoString(str, "user");
+ break;
+ case SVFOP_SESSION_USER:
+ appendStringInfoString(str, "session_user");
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ appendStringInfoString(str, "current_catalog");
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ appendStringInfoString(str, "current_schema");
+ break;
+ }
+
+ if (sql_value_function->typmod != -1)
+ {
+ appendStringInfo(str, "(%d)", sql_value_function->typmod);
+ }
+}
+
+static void deparseWithClause(StringInfo str, WithClause *with_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "WITH ");
+ if (with_clause->recursive)
+ appendStringInfoString(str, "RECURSIVE ");
+
+ foreach(lc, with_clause->ctes) {
+ deparseCommonTableExpr(str, castNode(CommonTableExpr, lfirst(lc)));
+ if (lnext(with_clause->ctes, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
+{
+ ListCell *lc;
+ bool need_alias_parens = join_expr->alias != NULL;
+ bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
+
+ if (need_alias_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseTableRef(str, join_expr->larg);
+
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->isNatural)
+ appendStringInfoString(str, "NATURAL ");
+
+ switch (join_expr->jointype)
+ {
+ case JOIN_INNER: /* matching tuple pairs only */
+ if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
+ appendStringInfoString(str, "CROSS ");
+ break;
+ case JOIN_LEFT: /* pairs + unmatched LHS tuples */
+ appendStringInfoString(str, "LEFT ");
+ break;
+ case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
+ appendStringInfoString(str, "FULL ");
+ break;
+ case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
+ appendStringInfoString(str, "RIGHT ");
+ break;
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ case JOIN_RIGHT_ANTI:
+ case JOIN_UNIQUE_OUTER:
+ case JOIN_UNIQUE_INNER:
+ // Only used by the planner/executor, not seen in parser output
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "JOIN ");
+
+ if (need_rarg_parens)
+ appendStringInfoChar(str, '(');
+ deparseTableRef(str, join_expr->rarg);
+ if (need_rarg_parens)
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+
+ if (join_expr->quals != NULL)
+ {
+ appendStringInfoString(str, "ON ");
+ deparseExpr(str, join_expr->quals);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(join_expr->usingClause) > 0)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseNameList(str, join_expr->usingClause);
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->join_using_alias)
+ {
+ appendStringInfoString(str, "AS ");
+ appendStringInfoString(str, join_expr->join_using_alias->aliasname);
+ }
+ }
+
+ if (need_alias_parens)
+ appendStringInfoString(str, ") ");
+
+ if (join_expr->alias != NULL)
+ deparseAlias(str, join_expr->alias);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCTESearchClause(StringInfo str, CTESearchClause *search_clause)
+{
+ appendStringInfoString(str, " SEARCH ");
+ if (search_clause->search_breadth_first)
+ appendStringInfoString(str, "BREADTH ");
+ else
+ appendStringInfoString(str, "DEPTH ");
+
+ appendStringInfoString(str, "FIRST BY ");
+
+ if (search_clause->search_col_list)
+ deparseColumnList(str, search_clause->search_col_list);
+
+ appendStringInfoString(str, " SET ");
+ appendStringInfoString(str, quote_identifier(search_clause->search_seq_column));
+}
+
+static void deparseCTECycleClause(StringInfo str, CTECycleClause *cycle_clause)
+{
+ appendStringInfoString(str, " CYCLE ");
+
+ if (cycle_clause->cycle_col_list)
+ deparseColumnList(str, cycle_clause->cycle_col_list);
+
+ appendStringInfoString(str, " SET ");
+ appendStringInfoString(str, quote_identifier(cycle_clause->cycle_mark_column));
+
+ if (cycle_clause->cycle_mark_value)
+ {
+ appendStringInfoString(str, " TO ");
+ deparseExpr(str, cycle_clause->cycle_mark_value);
+ }
+
+ if (cycle_clause->cycle_mark_default)
+ {
+ appendStringInfoString(str, " DEFAULT ");
+ deparseExpr(str, cycle_clause->cycle_mark_default);
+ }
+
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(cycle_clause->cycle_path_column));
+}
+
+static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
+{
+ deparseColId(str, cte->ctename);
+
+ if (list_length(cte->aliascolnames) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, cte->aliascolnames);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ switch (cte->ctematerialized) {
+ case CTEMaterializeDefault: /* no option specified */
+ break;
+ case CTEMaterializeAlways:
+ appendStringInfoString(str, "MATERIALIZED ");
+ break;
+ case CTEMaterializeNever:
+ appendStringInfoString(str, "NOT MATERIALIZED ");
+ break;
+ }
+
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, cte->ctequery);
+ appendStringInfoChar(str, ')');
+
+ if (cte->search_clause)
+ deparseCTESearchClause(str, cte->search_clause);
+ if (cte->cycle_clause)
+ deparseCTECycleClause(str, cte->cycle_clause);
+}
+
+static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
+{
+ if (range_subselect->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoChar(str, '(');
+ deparseSelectStmt(str, castNode(SelectStmt, range_subselect->subquery));
+ appendStringInfoChar(str, ')');
+
+ if (range_subselect->alias != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparseAlias(str, range_subselect->alias);
+ }
+}
+
+static void deparseRangeFunction(StringInfo str, RangeFunction *range_func)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (range_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ if (range_func->is_rowsfrom)
+ {
+ appendStringInfoString(str, "ROWS FROM ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->functions)
+ {
+ List *lfunc = castNode(List, lfirst(lc));
+ Assert(list_length(lfunc) == 2);
+ deparseFuncExprWindowless(str, linitial(lfunc));
+ appendStringInfoChar(str, ' ');
+ List *coldeflist = castNode(List, lsecond(lfunc));
+ if (list_length(coldeflist) > 0)
+ {
+ appendStringInfoString(str, "AS (");
+ foreach(lc2, coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc2)));
+ if (lnext(coldeflist, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ if (lnext(range_func->functions, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(list_length(linitial(range_func->functions)) == 2);
+ deparseFuncExprWindowless(str, linitial(linitial(range_func->functions)));
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (range_func->ordinality)
+ appendStringInfoString(str, "WITH ORDINALITY ");
+
+ if (range_func->alias != NULL)
+ {
+ deparseAlias(str, range_func->alias);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(range_func->coldeflist) > 0)
+ {
+ if (range_func->alias == NULL)
+ appendStringInfoString(str, "AS ");
+ appendStringInfoChar(str, '(');
+ foreach(lc, range_func->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(range_func->coldeflist, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAArrayExpr(StringInfo str, A_ArrayExpr *array_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ARRAY[");
+ deparseExprList(str, array_expr->elements);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
+{
+ ListCell *lc;
+
+ switch (row_expr->row_format)
+ {
+ case COERCE_EXPLICIT_CALL:
+ appendStringInfoString(str, "ROW");
+ break;
+ case COERCE_SQL_SYNTAX:
+ case COERCE_EXPLICIT_CAST:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCE_IMPLICIT_CAST:
+ // No prefix
+ break;
+ }
+
+ appendStringInfoString(str, "(");
+ deparseExprList(str, row_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context)
+{
+ bool need_parens = false;
+
+ Assert(type_cast->typeName != NULL);
+
+ if (IsA(type_cast->arg, A_Expr) || context == DEPARSE_NODE_CONTEXT_FUNC_EXPR)
+ {
+ appendStringInfoString(str, "CAST(");
+ deparseExpr(str, type_cast->arg);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, type_cast->typeName);
+ appendStringInfoChar(str, ')');
+ return;
+ }
+
+ if (IsA(type_cast->arg, A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, type_cast->arg);
+
+ if (list_length(type_cast->typeName->names) == 2 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
+ {
+ char *typename = strVal(lsecond(type_cast->typeName->names));
+ if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
+ {
+ appendStringInfoString(str, "char ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
+ {
+ /*
+ * Handle "bool" or "false" in the statement, which is represented as a typecast
+ * (other boolean casts should be represented as a cast, i.e. don't need special handling)
+ */
+ char *const_val = strVal(&a_const->val);
+ if (strcmp(const_val, "t") == 0)
+ {
+ appendStringInfoString(str, "true");
+ return;
+ }
+ if (strcmp(const_val, "f") == 0)
+ {
+ appendStringInfoString(str, "false");
+ return;
+ }
+ }
+ else if (strcmp(typename, "interval") == 0 && context == DEPARSE_NODE_CONTEXT_SET_STATEMENT && IsA(&a_const->val, String))
+ {
+ appendStringInfoString(str, "interval ");
+ deparseAConst(str, a_const);
+ deparseIntervalTypmods(str, type_cast->typeName);
+ return;
+ }
+ }
+
+ // Ensure negative values have wrapping parentheses
+ if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
+ {
+ need_parens = true;
+ }
+
+ if (list_length(type_cast->typeName->names) == 1 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "point") == 0 &&
+ a_const->location > type_cast->typeName->location)
+ {
+ appendStringInfoString(str, " point ");
+ deparseAConst(str, a_const);
+ return;
+ }
+ }
+
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, type_cast->arg);
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, "::");
+ deparseTypeName(str, type_cast->typeName);
+}
+
+static void deparseTypeName(StringInfo str, TypeName *type_name)
+{
+ ListCell *lc;
+ bool skip_typmods = false;
+
+ if (type_name->setof)
+ appendStringInfoString(str, "SETOF ");
+
+ if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
+ {
+ const char *name = strVal(lsecond(type_name->names));
+ if (strcmp(name, "bpchar") == 0)
+ {
+ appendStringInfoString(str, "char");
+ }
+ else if (strcmp(name, "varchar") == 0)
+ {
+ appendStringInfoString(str, "varchar");
+ }
+ else if (strcmp(name, "numeric") == 0)
+ {
+ appendStringInfoString(str, "numeric");
+ }
+ else if (strcmp(name, "bool") == 0)
+ {
+ appendStringInfoString(str, "boolean");
+ }
+ else if (strcmp(name, "int2") == 0)
+ {
+ appendStringInfoString(str, "smallint");
+ }
+ else if (strcmp(name, "int4") == 0)
+ {
+ appendStringInfoString(str, "int");
+ }
+ else if (strcmp(name, "int8") == 0)
+ {
+ appendStringInfoString(str, "bigint");
+ }
+ else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
+ {
+ appendStringInfoString(str, "real");
+ }
+ else if (strcmp(name, "float8") == 0)
+ {
+ appendStringInfoString(str, "double precision");
+ }
+ else if (strcmp(name, "time") == 0)
+ {
+ appendStringInfoString(str, "time");
+ }
+ else if (strcmp(name, "timetz") == 0)
+ {
+ appendStringInfoString(str, "time ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "timestamp") == 0)
+ {
+ appendStringInfoString(str, "timestamp");
+ }
+ else if (strcmp(name, "timestamptz") == 0)
+ {
+ appendStringInfoString(str, "timestamp ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ appendStringInfoString(str, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
+ {
+ appendStringInfoString(str, "interval");
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
+ {
+ appendStringInfoString(str, "interval");
+ deparseIntervalTypmods(str, type_name);
+
+ skip_typmods = true;
+ }
+ else
+ {
+ appendStringInfoString(str, "pg_catalog.");
+ appendStringInfoString(str, name);
+ }
+ }
+ else
+ {
+ deparseAnyName(str, type_name->names);
+ }
+
+ if (list_length(type_name->typmods) > 0 && !skip_typmods)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, type_name->typmods)
+ {
+ if (IsA(lfirst(lc), A_Const))
+ deparseAConst(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ParamRef))
+ deparseParamRef(str, lfirst(lc));
+ else if (IsA(lfirst(lc), ColumnRef))
+ deparseColumnRef(str, lfirst(lc));
+ else
+ Assert(false);
+
+ if (lnext(type_name->typmods, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ foreach(lc, type_name->arrayBounds)
+ {
+ appendStringInfoChar(str, '[');
+ if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
+ deparseSignedIconst(str, lfirst(lc));
+ appendStringInfoChar(str, ']');
+ }
+
+ if (type_name->pct_type)
+ appendStringInfoString(str, "%type");
+}
+
+// Handle typemods for Interval types separately
+// so that they can be applied appropriately for different contexts.
+// For example, when using `SET` a query like `INTERVAL 'x' hour TO minute`
+// the `INTERVAL` keyword is specified first.
+// In all other contexts, intervals use the `'x'::interval` style.
+static void deparseIntervalTypmods(StringInfo str, TypeName *type_name)
+{
+ const char *name = strVal(lsecond(type_name->names));
+ Assert(strcmp(name, "interval") == 0);
+ Assert(list_length(type_name->typmods) >= 1);
+ Assert(IsA(linitial(type_name->typmods), A_Const));
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
+
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
+
+ // This logic is based on intervaltypmodout in timestamp.c
+ switch (fields)
+ {
+ case INTERVAL_MASK(YEAR):
+ appendStringInfoString(str, " year");
+ break;
+ case INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " month");
+ break;
+ case INTERVAL_MASK(DAY):
+ appendStringInfoString(str, " day");
+ break;
+ case INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " hour");
+ break;
+ case INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " minute");
+ break;
+ case INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " second");
+ break;
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+ appendStringInfoString(str, " year to month");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+ appendStringInfoString(str, " day to hour");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " day to minute");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " day to second");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ appendStringInfoString(str, " hour to minute");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " hour to second");
+ break;
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ appendStringInfoString(str, " minute to second");
+ break;
+ case INTERVAL_FULL_RANGE:
+ // Nothing
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (list_length(type_name->typmods) == 2)
+ {
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
+ if (precision != INTERVAL_FULL_PRECISION)
+ appendStringInfo(str, "(%d)", precision);
+ }
+}
+
+static void deparseNullTest(StringInfo str, NullTest *null_test)
+{
+ // argisrow is always false in raw parser output
+ Assert(null_test->argisrow == false);
+
+ deparseExpr(str, (Node *) null_test->arg);
+ switch (null_test->nulltesttype)
+ {
+ case IS_NULL:
+ appendStringInfoString(str, " IS NULL");
+ break;
+ case IS_NOT_NULL:
+ appendStringInfoString(str, " IS NOT NULL");
+ break;
+ }
+}
+
+static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CASE ");
+
+ if (case_expr->arg != NULL)
+ {
+ deparseExpr(str, (Node *) case_expr->arg);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, case_expr->args)
+ {
+ deparseCaseWhen(str, castNode(CaseWhen, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (case_expr->defresult != NULL)
+ {
+ appendStringInfoString(str, "ELSE ");
+ deparseExpr(str, (Node *) case_expr->defresult);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "END");
+}
+
+static void deparseCaseWhen(StringInfo str, CaseWhen *case_when)
+{
+ appendStringInfoString(str, "WHEN ");
+ deparseExpr(str, (Node *) case_when->expr);
+ appendStringInfoString(str, " THEN ");
+ deparseExpr(str, (Node *) case_when->result);
+}
+
+static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection)
+{
+ ListCell *lc;
+ bool need_parens =
+ IsA(a_indirection->arg, A_Indirection) ||
+ IsA(a_indirection->arg, FuncCall) ||
+ IsA(a_indirection->arg, A_Expr) ||
+ IsA(a_indirection->arg, TypeCast) ||
+ IsA(a_indirection->arg, RowExpr) ||
+ (IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices));
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, a_indirection->arg);
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ deparseOptIndirection(str, a_indirection->indirection, 0);
+}
+
+static void deparseAIndices(StringInfo str, A_Indices *a_indices)
+{
+ appendStringInfoChar(str, '[');
+ if (a_indices->lidx != NULL)
+ deparseExpr(str, a_indices->lidx);
+ if (a_indices->is_slice)
+ appendStringInfoChar(str, ':');
+ if (a_indices->uidx != NULL)
+ deparseExpr(str, a_indices->uidx);
+ appendStringInfoChar(str, ']');
+}
+
+static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr)
+{
+ appendStringInfoString(str, "COALESCE(");
+ deparseExprList(str, coalesce_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr)
+{
+ switch (min_max_expr->op)
+ {
+ case IS_GREATEST:
+ appendStringInfoString(str, "GREATEST(");
+ break;
+ case IS_LEAST:
+ appendStringInfoString(str, "LEAST(");
+ break;
+ }
+ deparseExprList(str, min_max_expr->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test)
+{
+ bool need_parens = IsA(boolean_test->arg, BoolExpr);
+
+ if (need_parens)
+ appendStringInfoChar(str, '(');
+
+ deparseExpr(str, (Node *) boolean_test->arg);
+
+ if (need_parens)
+ appendStringInfoChar(str, ')');
+
+ switch (boolean_test->booltesttype)
+ {
+ case IS_TRUE:
+ appendStringInfoString(str, " IS TRUE");
+ break;
+ case IS_NOT_TRUE:
+ appendStringInfoString(str, " IS NOT TRUE");
+ break;
+ case IS_FALSE:
+ appendStringInfoString(str, " IS FALSE");
+ break;
+ case IS_NOT_FALSE:
+ appendStringInfoString(str, " IS NOT FALSE");
+ break;
+ case IS_UNKNOWN:
+ appendStringInfoString(str, " IS UNKNOWN");
+ break;
+ case IS_NOT_UNKNOWN:
+ appendStringInfoString(str, " IS NOT UNKNOWN");
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
+{
+ ListCell *lc;
+
+ if (column_def->colname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(column_def->colname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->typeName != NULL)
+ {
+ deparseTypeName(str, column_def->typeName);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->storage_name)
+ {
+ appendStringInfoString(str, "STORAGE ");
+ appendStringInfoString(str, column_def->storage_name);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->raw_default != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseExpr(str, column_def->raw_default);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->compression != NULL)
+ {
+ appendStringInfoString(str, "COMPRESSION ");
+ appendStringInfoString(str, column_def->compression);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->fdwoptions != NULL)
+ {
+ deparseCreateGenericOptions(str, column_def->fdwoptions);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, column_def->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (column_def->collClause != NULL)
+ {
+ deparseCollateClause(str, column_def->collClause);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInsertOverride(StringInfo str, OverridingKind override)
+{
+ switch (override)
+ {
+ case OVERRIDING_NOT_SET:
+ // Do nothing
+ break;
+ case OVERRIDING_USER_VALUE:
+ appendStringInfoString(str, "OVERRIDING USER VALUE ");
+ break;
+ case OVERRIDING_SYSTEM_VALUE:
+ appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
+ break;
+ }
+}
+
+static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (insert_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, insert_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "INSERT INTO ");
+ deparseRangeVar(str, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(insert_stmt->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseInsertColumnList(str, insert_stmt->cols);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseInsertOverride(str, insert_stmt->override);
+
+ if (insert_stmt->selectStmt != NULL)
+ {
+ deparseSelectStmt(str, castNode(SelectStmt, insert_stmt->selectStmt));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "DEFAULT VALUES ");
+ }
+
+ if (insert_stmt->onConflictClause != NULL)
+ {
+ deparseOnConflictClause(str, insert_stmt->onConflictClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(insert_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, insert_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseInferClause(StringInfo str, InferClause *infer_clause)
+{
+ ListCell *lc;
+
+ if (list_length(infer_clause->indexElems) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, infer_clause->indexElems)
+ {
+ deparseIndexElem(str, lfirst(lc));
+ if (lnext(infer_clause->indexElems, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ if (infer_clause->conname != NULL)
+ {
+ appendStringInfoString(str, "ON CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(infer_clause->conname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, infer_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ON CONFLICT ");
+
+ if (on_conflict_clause->infer != NULL)
+ {
+ deparseInferClause(str, on_conflict_clause->infer);
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (on_conflict_clause->action)
+ {
+ case ONCONFLICT_NONE:
+ Assert(false);
+ break;
+ case ONCONFLICT_NOTHING:
+ appendStringInfoString(str, "DO NOTHING ");
+ break;
+ case ONCONFLICT_UPDATE:
+ appendStringInfoString(str, "DO UPDATE ");
+ break;
+ }
+
+ if (list_length(on_conflict_clause->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, on_conflict_clause->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, on_conflict_clause->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
+{
+ ListCell* lc;
+ ListCell* lc2;
+ ListCell* lc3;
+
+ if (update_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, update_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "UPDATE ");
+ deparseRangeVar(str, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(update_stmt->targetList) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseSetClauseList(str, update_stmt->targetList);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseFromClause(str, update_stmt->fromClause);
+ deparseWhereOrCurrentClause(str, update_stmt->whereClause);
+
+ if (list_length(update_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, update_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseMergeStmt(StringInfo str, MergeStmt *merge_stmt)
+{
+ if (merge_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, merge_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "MERGE INTO ");
+ deparseRangeVar(str, merge_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ deparseTableRef(str, merge_stmt->sourceRelation);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "ON ");
+ deparseExpr(str, merge_stmt->joinCondition);
+ appendStringInfoChar(str, ' ');
+
+ ListCell *lc, *lc2;
+ foreach (lc, merge_stmt->mergeWhenClauses)
+ {
+ MergeWhenClause *clause = castNode(MergeWhenClause, lfirst(lc));
+
+ appendStringInfoString(str, "WHEN ");
+
+ if (!clause->matched)
+ {
+ appendStringInfoString(str, "NOT ");
+ }
+
+ appendStringInfoString(str, "MATCHED ");
+
+ if (clause->condition)
+ {
+ appendStringInfoString(str, "AND ");
+ deparseExpr(str, clause->condition);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "THEN ");
+
+ switch (clause->commandType) {
+ case CMD_INSERT:
+ appendStringInfoString(str, "INSERT ");
+
+ if (clause->targetList) {
+ appendStringInfoChar(str, '(');
+ deparseInsertColumnList(str, clause->targetList);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseInsertOverride(str, clause->override);
+
+ if (clause->values) {
+ appendStringInfoString(str, "VALUES (");
+ deparseExprList(str, clause->values);
+ appendStringInfoString(str, ")");
+ } else {
+ appendStringInfoString(str, "DEFAULT VALUES ");
+ }
+
+ break;
+ case CMD_UPDATE:
+ appendStringInfoString(str, "UPDATE SET ");
+ deparseSetClauseList(str, clause->targetList);
+ break;
+ case CMD_DELETE:
+ appendStringInfoString(str, "DELETE");
+ break;
+ case CMD_NOTHING:
+ appendStringInfoString(str, "DO NOTHING");
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted command type in merge statement: %d", clause->commandType);
+ break;
+ }
+
+ if (lfirst(lc) != llast(merge_stmt->mergeWhenClauses))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
+{
+ if (delete_stmt->withClause != NULL)
+ {
+ deparseWithClause(str, delete_stmt->withClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "DELETE FROM ");
+ deparseRangeVar(str, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (delete_stmt->usingClause != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ deparseFromList(str, delete_stmt->usingClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereOrCurrentClause(str, delete_stmt->whereClause);
+
+ if (list_length(delete_stmt->returningList) > 0)
+ {
+ appendStringInfoString(str, "RETURNING ");
+ deparseTargetList(str, delete_stmt->returningList);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLockingClause(StringInfo str, LockingClause *locking_clause)
+{
+ ListCell *lc;
+
+ switch (locking_clause->strength)
+ {
+ case LCS_NONE:
+ /* no such clause - only used in PlanRowMark */
+ Assert(false);
+ break;
+ case LCS_FORKEYSHARE:
+ appendStringInfoString(str, "FOR KEY SHARE ");
+ break;
+ case LCS_FORSHARE:
+ appendStringInfoString(str, "FOR SHARE ");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ appendStringInfoString(str, "FOR NO KEY UPDATE ");
+ break;
+ case LCS_FORUPDATE:
+ appendStringInfoString(str, "FOR UPDATE ");
+ break;
+ }
+
+ if (list_length(locking_clause->lockedRels) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseQualifiedNameList(str, locking_clause->lockedRels);
+ }
+
+ switch (locking_clause->waitPolicy)
+ {
+ case LockWaitError:
+ appendStringInfoString(str, "NOWAIT");
+ break;
+ case LockWaitSkip:
+ appendStringInfoString(str, "SKIP LOCKED");
+ break;
+ case LockWaitBlock:
+ // Default
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default)
+{
+ appendStringInfoString(str, "DEFAULT");
+}
+
+static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ appendStringInfoString(str, "CREATE CAST (");
+ deparseTypeName(str, create_cast_stmt->sourcetype);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, create_cast_stmt->targettype);
+ appendStringInfoString(str, ") ");
+
+ if (create_cast_stmt->func != NULL)
+ {
+ appendStringInfoString(str, "WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_cast_stmt->func);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_cast_stmt->inout)
+ {
+ appendStringInfoString(str, "WITH INOUT ");
+ }
+ else
+ {
+ appendStringInfoString(str, "WITHOUT FUNCTION ");
+ }
+
+ switch (create_cast_stmt->context)
+ {
+ case COERCION_IMPLICIT:
+ appendStringInfoString(str, "AS IMPLICIT");
+ break;
+ case COERCION_ASSIGNMENT:
+ appendStringInfoString(str, "AS ASSIGNMENT");
+ break;
+ case COERCION_PLPGSQL:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCION_EXPLICIT:
+ // Default
+ break;
+ }
+}
+
+static void deparseCreateOpClassStmt(StringInfo str, CreateOpClassStmt *create_op_class_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE OPERATOR CLASS ");
+
+ deparseAnyName(str, create_op_class_stmt->opclassname);
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->isDefault)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "FOR TYPE ");
+ deparseTypeName(str, create_op_class_stmt->datatype);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_class_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_op_class_stmt->opfamilyname != NULL)
+ {
+ appendStringInfoString(str, "FAMILY ");
+ deparseAnyName(str, create_op_class_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "AS ");
+ deparseOpclassItemList(str, create_op_class_stmt->items);
+}
+
+static void deparseCreateOpFamilyStmt(StringInfo str, CreateOpFamilyStmt *create_op_family_stmt)
+{
+ appendStringInfoString(str, "CREATE OPERATOR FAMILY ");
+
+ deparseAnyName(str, create_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_op_family_stmt->amname));
+}
+
+static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item)
+{
+ ListCell *lc = NULL;
+
+ switch (create_op_class_item->itemtype)
+ {
+ case OPCLASS_ITEM_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+
+ if (create_op_class_item->name != NULL)
+ {
+ if (create_op_class_item->name->objargs != NULL)
+ deparseOperatorWithArgtypes(str, create_op_class_item->name);
+ else
+ deparseAnyOperator(str, create_op_class_item->name->objname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_op_class_item->order_family != NULL)
+ {
+ appendStringInfoString(str, "FOR ORDER BY ");
+ deparseAnyName(str, create_op_class_item->order_family);
+ }
+
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoChar(str, ')');
+ }
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ appendStringInfo(str, "%d ", create_op_class_item->number);
+ if (create_op_class_item->class_args != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, create_op_class_item->class_args);
+ appendStringInfoString(str, ") ");
+ }
+ if (create_op_class_item->name != NULL)
+ deparseFunctionWithArgtypes(str, create_op_class_item->name);
+ removeTrailingSpace(str);
+ break;
+ case OPCLASS_ITEM_STORAGETYPE:
+ appendStringInfoString(str, "STORAGE ");
+ deparseTypeName(str, create_op_class_item->storedtype);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseTableLikeClause(StringInfo str, TableLikeClause *table_like_clause)
+{
+ appendStringInfoString(str, "LIKE ");
+ deparseRangeVar(str, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
+ appendStringInfoString(str, "INCLUDING ALL ");
+ else
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+ appendStringInfoString(str, "INCLUDING COMMENTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION)
+ appendStringInfoString(str, "INCLUDING COMPRESSION ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ appendStringInfoString(str, "INCLUDING CONSTRAINTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
+ appendStringInfoString(str, "INCLUDING DEFAULTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
+ appendStringInfoString(str, "INCLUDING IDENTITY ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED)
+ appendStringInfoString(str, "INCLUDING GENERATED ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ appendStringInfoString(str, "INCLUDING INDEXES ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
+ appendStringInfoString(str, "INCLUDING STATISTICS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ appendStringInfoString(str, "INCLUDING STORAGE ");
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt)
+{
+ ListCell *lc;
+
+ Assert(create_domain_stmt->typeName != NULL);
+
+ appendStringInfoString(str, "CREATE DOMAIN ");
+ deparseAnyName(str, create_domain_stmt->domainname);
+ appendStringInfoString(str, " AS ");
+
+ deparseTypeName(str, create_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (create_domain_stmt->collClause != NULL)
+ {
+ deparseCollateClause(str, create_domain_stmt->collClause);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_domain_stmt->constraints)
+ {
+ deparseConstraint(str, castNode(Constraint, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateExtensionStmt(StringInfo str, CreateExtensionStmt *create_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE EXTENSION ");
+
+ if (create_extension_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseColId(str, create_extension_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, create_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "schema") == 0)
+ {
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "cascade") == 0)
+ {
+ appendStringInfoString(str, "CASCADE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraint(StringInfo str, Constraint *constraint)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(constraint->conname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ switch (constraint->contype) {
+ case CONSTR_NULL:
+ appendStringInfoString(str, "NULL ");
+ break;
+ case CONSTR_NOTNULL:
+ appendStringInfoString(str, "NOT NULL ");
+ break;
+ case CONSTR_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ deparseBExpr(str, constraint->raw_expr);
+ break;
+ case CONSTR_IDENTITY:
+ appendStringInfoString(str, "GENERATED ");
+ switch (constraint->generated_when)
+ {
+ case ATTRIBUTE_IDENTITY_ALWAYS:
+ appendStringInfoString(str, "ALWAYS ");
+ break;
+ case ATTRIBUTE_IDENTITY_BY_DEFAULT:
+ appendStringInfoString(str, "BY DEFAULT ");
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoString(str, "AS IDENTITY ");
+ deparseOptParenthesizedSeqOptList(str, constraint->options);
+ break;
+ case CONSTR_GENERATED:
+ Assert(constraint->generated_when == ATTRIBUTE_IDENTITY_ALWAYS);
+ appendStringInfoString(str, "GENERATED ALWAYS AS (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") STORED ");
+ break;
+ case CONSTR_CHECK:
+ appendStringInfoString(str, "CHECK (");
+ deparseExpr(str, constraint->raw_expr);
+ appendStringInfoString(str, ") ");
+ break;
+ case CONSTR_PRIMARY:
+ appendStringInfoString(str, "PRIMARY KEY ");
+ break;
+ case CONSTR_UNIQUE:
+ appendStringInfoString(str, "UNIQUE ");
+ if (constraint->nulls_not_distinct)
+ appendStringInfoString(str, "NULLS NOT DISTINCT ");
+ break;
+ case CONSTR_EXCLUSION:
+ appendStringInfoString(str, "EXCLUDE ");
+ if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(constraint->access_method));
+ appendStringInfoChar(str, ' ');
+ }
+ appendStringInfoChar(str, '(');
+ foreach(lc, constraint->exclusions)
+ {
+ List *exclusion = castNode(List, lfirst(lc));
+ Assert(list_length(exclusion) == 2);
+ deparseIndexElem(str, castNode(IndexElem, linitial(exclusion)));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyOperator(str, castNode(List, lsecond(exclusion)));
+ if (lnext(constraint->exclusions, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ if (constraint->where_clause != NULL)
+ {
+ appendStringInfoString(str, "WHERE (");
+ deparseExpr(str, constraint->where_clause);
+ appendStringInfoString(str, ") ");
+ }
+ break;
+ case CONSTR_FOREIGN:
+ if (list_length(constraint->fk_attrs) > 0)
+ appendStringInfoString(str, "FOREIGN KEY ");
+ break;
+ case CONSTR_ATTR_DEFERRABLE:
+ appendStringInfoString(str, "DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ appendStringInfoString(str, "NOT DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_DEFERRED:
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+ break;
+ case CONSTR_ATTR_IMMEDIATE:
+ appendStringInfoString(str, "INITIALLY IMMEDIATE ");
+ break;
+ }
+
+ if (list_length(constraint->keys) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->keys);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (list_length(constraint->fk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->fk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (constraint->pktable != NULL)
+ {
+ appendStringInfoString(str, "REFERENCES ");
+ deparseRangeVar(str, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ if (list_length(constraint->pk_attrs) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, constraint->pk_attrs);
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ switch (constraint->fk_matchtype)
+ {
+ case FKCONSTR_MATCH_SIMPLE:
+ // Default
+ break;
+ case FKCONSTR_MATCH_FULL:
+ appendStringInfoString(str, "MATCH FULL ");
+ break;
+ case FKCONSTR_MATCH_PARTIAL:
+ // Not implemented in Postgres
+ Assert(false);
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_upd_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON UPDATE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON UPDATE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ appendStringInfoString(str, "ON UPDATE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON UPDATE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_del_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ appendStringInfoString(str, "ON DELETE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ appendStringInfoString(str, "ON DELETE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ case FKCONSTR_ACTION_SETDEFAULT:
+ appendStringInfoString(str, "ON DELETE SET ");
+
+ switch (constraint->fk_del_action) {
+ case FKCONSTR_ACTION_SETDEFAULT: appendStringInfoString(str, "DEFAULT "); break;
+ case FKCONSTR_ACTION_SETNULL: appendStringInfoString(str, "NULL "); break;
+ }
+
+ if (constraint->fk_del_set_cols) {
+ appendStringInfoString(str, "(");
+ ListCell *lc;
+ foreach (lc, constraint->fk_del_set_cols) {
+ appendStringInfoString(str, strVal(lfirst(lc)));
+ if (lfirst(lc) != llast(constraint->fk_del_set_cols))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ")");
+ }
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ if (list_length(constraint->including) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ deparseColumnList(str, constraint->including);
+ appendStringInfoString(str, ") ");
+ }
+
+ switch (constraint->contype)
+ {
+ case CONSTR_PRIMARY:
+ case CONSTR_UNIQUE:
+ case CONSTR_EXCLUSION:
+ deparseOptWith(str, constraint->options);
+ break;
+ default:
+ break;
+ }
+
+ if (constraint->indexname != NULL)
+ appendStringInfo(str, "USING INDEX %s ", quote_identifier(constraint->indexname));
+
+ if (constraint->indexspace != NULL)
+ appendStringInfo(str, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
+
+ if (constraint->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (constraint->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (constraint->is_no_inherit)
+ appendStringInfoString(str, "NO INHERIT ");
+
+ if (constraint->skip_validation)
+ appendStringInfoString(str, "NOT VALID ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReturnStmt(StringInfo str, ReturnStmt *return_stmt)
+{
+ appendStringInfoString(str, "RETURN ");
+ deparseExpr(str, return_stmt->returnval);
+}
+
+static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
+{
+ ListCell *lc;
+ bool tableFunc = false;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_function_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_function_stmt->is_procedure)
+ appendStringInfoString(str, "PROCEDURE ");
+ else
+ appendStringInfoString(str, "FUNCTION ");
+
+ deparseFuncName(str, create_function_stmt->funcname);
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode != FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc) && castNode(FunctionParameter, lfirst(lnext(create_function_stmt->parameters, lc)))->mode != FUNC_PARAM_TABLE)
+ appendStringInfoString(str, ", ");
+ }
+ else
+ {
+ tableFunc = true;
+ }
+ }
+ appendStringInfoString(str, ") ");
+
+ if (tableFunc)
+ {
+ appendStringInfoString(str, "RETURNS TABLE (");
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode == FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(str, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc))
+ appendStringInfoString(str, ", ");
+ }
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_function_stmt->returnType != NULL)
+ {
+ appendStringInfoString(str, "RETURNS ");
+ deparseTypeName(str, create_function_stmt->returnType);
+ appendStringInfoChar(str, ' ');
+ }
+
+ foreach(lc, create_function_stmt->options)
+ {
+ deparseCreateFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_function_stmt->sql_body)
+ {
+ /* RETURN or BEGIN ... END
+ */
+ if (IsA(create_function_stmt->sql_body, ReturnStmt))
+ {
+ deparseReturnStmt(str, castNode(ReturnStmt, create_function_stmt->sql_body));
+ }
+ else
+ {
+ appendStringInfoString(str, "BEGIN ATOMIC ");
+ if (IsA(create_function_stmt->sql_body, List), linitial((List *) create_function_stmt->sql_body) != NULL)
+ {
+ List *body_stmt_list = castNode(List, linitial((List *) create_function_stmt->sql_body));
+ foreach(lc, body_stmt_list)
+ {
+ if (IsA(lfirst(lc), ReturnStmt))
+ {
+ deparseReturnStmt(str, lfirst_node(ReturnStmt, lc));
+ appendStringInfoString(str, "; ");
+ }
+ else
+ {
+ deparseStmt(str, lfirst(lc));
+ appendStringInfoString(str, "; ");
+ }
+ }
+ }
+
+ appendStringInfoString(str, "END ");
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter)
+{
+ switch (function_parameter->mode)
+ {
+ case FUNC_PARAM_IN: /* input only */
+ appendStringInfoString(str, "IN ");
+ break;
+ case FUNC_PARAM_OUT: /* output only */
+ appendStringInfoString(str, "OUT ");
+ break;
+ case FUNC_PARAM_INOUT: /* both */
+ appendStringInfoString(str, "INOUT ");
+ break;
+ case FUNC_PARAM_VARIADIC: /* variadic (always input) */
+ appendStringInfoString(str, "VARIADIC ");
+ break;
+ case FUNC_PARAM_TABLE: /* table function output column */
+ // No special annotation, the caller is expected to correctly put
+ // this into the RETURNS part of the CREATE FUNCTION statement
+ break;
+ case FUNC_PARAM_DEFAULT:
+ // Default
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (function_parameter->name != NULL)
+ {
+ appendStringInfoString(str, function_parameter->name);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseTypeName(str, function_parameter->argType);
+ appendStringInfoChar(str, ' ');
+
+ if (function_parameter->defexpr != NULL)
+ {
+ appendStringInfoString(str, "= ");
+ deparseExpr(str, function_parameter->defexpr);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_stmt)
+{
+ appendStringInfoString(str, "CHECKPOINT");
+}
+
+static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE SCHEMA ");
+
+ if (create_schema_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (create_schema_stmt->schemaname)
+ {
+ deparseColId(str, create_schema_stmt->schemaname);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->authrole != NULL)
+ {
+ appendStringInfoString(str, "AUTHORIZATION ");
+ deparseRoleSpec(str, create_schema_stmt->authrole);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_schema_stmt->schemaElts)
+ {
+ foreach(lc, create_schema_stmt->schemaElts)
+ {
+ deparseSchemaStmt(str, lfirst(lc));
+ if (lnext(create_schema_stmt->schemaElts, lc))
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleSetStmt(StringInfo str, AlterRoleSetStmt *alter_role_set_stmt)
+{
+ appendStringInfoString(str, "ALTER ROLE ");
+
+ if (alter_role_set_stmt->role == NULL)
+ appendStringInfoString(str, "ALL");
+ else
+ deparseRoleSpec(str, alter_role_set_stmt->role);
+
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_set_stmt->database != NULL)
+ {
+ appendStringInfoString(str, "IN DATABASE ");
+ appendStringInfoString(str, quote_identifier(alter_role_set_stmt->database));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseVariableSetStmt(str, alter_role_set_stmt->setstmt);
+}
+
+static void deparseCreateConversionStmt(StringInfo str, CreateConversionStmt *create_conversion_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_conversion_stmt->def)
+ appendStringInfoString(str, "DEFAULT ");
+
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, create_conversion_stmt->conversion_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "FOR ");
+ deparseStringLiteral(str, create_conversion_stmt->for_encoding_name);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, create_conversion_stmt->to_encoding_name);
+
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, create_conversion_stmt->func_name);
+}
+
+static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
+{
+ switch (role_spec->roletype)
+ {
+ case ROLESPEC_CSTRING:
+ Assert(role_spec->rolename != NULL);
+ appendStringInfoString(str, quote_identifier(role_spec->rolename));
+ break;
+ case ROLESPEC_CURRENT_ROLE:
+ appendStringInfoString(str, "CURRENT_ROLE");
+ break;
+ case ROLESPEC_CURRENT_USER:
+ appendStringInfoString(str, "CURRENT_USER");
+ break;
+ case ROLESPEC_SESSION_USER:
+ appendStringInfoString(str, "SESSION_USER");
+ break;
+ case ROLESPEC_PUBLIC:
+ appendStringInfoString(str, "public");
+ break;
+ }
+}
+
+// "part_elem" in gram.y
+static void deparsePartitionElem(StringInfo str, PartitionElem *partition_elem)
+{
+ ListCell *lc;
+
+ if (partition_elem->name != NULL)
+ {
+ deparseColId(str, partition_elem->name);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (partition_elem->expr != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, partition_elem->expr);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptCollate(str, partition_elem->collation);
+ deparseAnyName(str, partition_elem->opclass);
+
+ removeTrailingSpace(str);
+}
+
+static void deparsePartitionSpec(StringInfo str, PartitionSpec *partition_spec)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "PARTITION BY ");
+
+ switch (partition_spec->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ appendStringInfoString(str, "LIST");
+ break;
+ case PARTITION_STRATEGY_HASH:
+ appendStringInfoString(str, "HASH");
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ appendStringInfoString(str, "RANGE");
+ break;
+ }
+
+ appendStringInfoChar(str, '(');
+ foreach(lc, partition_spec->partParams)
+ {
+ deparsePartitionElem(str, castNode(PartitionElem, lfirst(lc)));
+ if (lnext(partition_spec->partParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparsePartitionBoundSpec(StringInfo str, PartitionBoundSpec *partition_bound_spec)
+{
+ ListCell *lc;
+
+ if (partition_bound_spec->is_default)
+ {
+ appendStringInfoString(str, "DEFAULT");
+ return;
+ }
+
+ appendStringInfoString(str, "FOR VALUES ");
+
+ switch (partition_bound_spec->strategy)
+ {
+ case PARTITION_STRATEGY_HASH:
+ appendStringInfo(str, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
+ break;
+ case PARTITION_STRATEGY_LIST:
+ appendStringInfoString(str, "IN (");
+ deparseExprList(str, partition_bound_spec->listdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ appendStringInfoString(str, "FROM (");
+ deparseExprList(str, partition_bound_spec->lowerdatums);
+ appendStringInfoString(str, ") TO (");
+ deparseExprList(str, partition_bound_spec->upperdatums);
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
+{
+ deparseRangeVar(str, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (partition_cmd->bound != NULL)
+ {
+ appendStringInfoChar(str, ' ');
+ deparsePartitionBoundSpec(str, partition_cmd->bound);
+ }
+ if (partition_cmd->concurrent)
+ appendStringInfoString(str, " CONCURRENTLY ");
+}
+
+// "TableElement" in gram.y
+static void deparseTableElement(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnDef:
+ deparseColumnDef(str, castNode(ColumnDef, node));
+ break;
+ case T_TableLikeClause:
+ deparseTableLikeClause(str, castNode(TableLikeClause, node));
+ break;
+ case T_Constraint:
+ deparseConstraint(str, castNode(Constraint, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseCreateStmt(StringInfo str, CreateStmt *create_stmt, bool is_foreign_table)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (is_foreign_table)
+ appendStringInfoString(str, "FOREIGN ");
+
+ deparseOptTemp(str, create_stmt->relation->relpersistence);
+
+ appendStringInfoString(str, "TABLE ");
+
+ if (create_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_stmt->ofTypename != NULL)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseTypeName(str, create_stmt->ofTypename);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ Assert(list_length(create_stmt->inhRelations) == 1);
+ appendStringInfoString(str, "PARTITION OF ");
+ deparseRangeVar(str, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(create_stmt->tableElts) > 0)
+ {
+ // In raw parse output tableElts contains both columns and constraints
+ // (and the constraints field is NIL)
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_stmt->tableElts)
+ {
+ deparseTableElement(str, lfirst(lc));
+ if (lnext(create_stmt->tableElts, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
+ {
+ appendStringInfoString(str, "() ");
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ deparsePartitionBoundSpec(str, create_stmt->partbound);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ deparseOptInherit(str, create_stmt->inhRelations);
+ }
+
+ if (create_stmt->partspec != NULL)
+ {
+ deparsePartitionSpec(str, create_stmt->partspec);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(create_stmt->accessMethod));
+ }
+
+ deparseOptWith(str, create_stmt->options);
+
+ switch (create_stmt->oncommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No ON COMMIT clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ appendStringInfoString(str, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (create_stmt->tablespacename != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(create_stmt->tablespacename));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateFdwStmt(StringInfo str, CreateFdwStmt *create_fdw_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, create_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseCreateGenericOptions(str, create_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFdwStmt(StringInfo str, AlterFdwStmt *alter_fdw_stmt)
+{
+ appendStringInfoString(str, "ALTER FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(alter_fdw_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(str, alter_fdw_stmt->func_options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_fdw_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_fdw_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateForeignServerStmt(StringInfo str, CreateForeignServerStmt *create_foreign_server_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SERVER ");
+ if (create_foreign_server_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (create_foreign_server_stmt->servertype != NULL)
+ {
+ appendStringInfoString(str, "TYPE ");
+ deparseStringLiteral(str, create_foreign_server_stmt->servertype);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_foreign_server_stmt->version != NULL)
+ {
+ appendStringInfoString(str, "VERSION ");
+ deparseStringLiteral(str, create_foreign_server_stmt->version);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->fdwname));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterForeignServerStmt(StringInfo str, AlterForeignServerStmt *alter_foreign_server_stmt)
+{
+ appendStringInfoString(str, "ALTER SERVER ");
+
+ appendStringInfoString(str, quote_identifier(alter_foreign_server_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_foreign_server_stmt->has_version)
+ {
+ appendStringInfoString(str, "VERSION ");
+ if (alter_foreign_server_stmt->version != NULL)
+ deparseStringLiteral(str, alter_foreign_server_stmt->version);
+ else
+ appendStringInfoString(str, "NULL");
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (list_length(alter_foreign_server_stmt->options) > 0)
+ deparseAlterGenericOptions(str, alter_foreign_server_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateUserMappingStmt(StringInfo str, CreateUserMappingStmt *create_user_mapping_stmt)
+{
+ appendStringInfoString(str, "CREATE USER MAPPING ");
+ if (create_user_mapping_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, create_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(create_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, create_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreatedbStmt(StringInfo str, CreatedbStmt *createdb_stmt)
+{
+ appendStringInfoString(str, "CREATE DATABASE ");
+ deparseColId(str, createdb_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, createdb_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterUserMappingStmt(StringInfo str, AlterUserMappingStmt *alter_user_mapping_stmt)
+{
+ appendStringInfoString(str, "ALTER USER MAPPING FOR ");
+ deparseRoleSpec(str, alter_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(alter_user_mapping_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ deparseAlterGenericOptions(str, alter_user_mapping_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropUserMappingStmt(StringInfo str, DropUserMappingStmt *drop_user_mapping_stmt)
+{
+ appendStringInfoString(str, "DROP USER MAPPING ");
+
+ if (drop_user_mapping_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, "FOR ");
+ deparseRoleSpec(str, drop_user_mapping_stmt->user);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "SERVER ");
+ appendStringInfoString(str, quote_identifier(drop_user_mapping_stmt->servername));
+}
+
+static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "SECURITY LABEL ");
+
+ if (sec_label_stmt->provider != NULL)
+ {
+ appendStringInfoString(str, "FOR ");
+ appendStringInfoString(str, quote_identifier(sec_label_stmt->provider));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ switch (sec_label_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseAnyName(str, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseValue(str, (union ValUnion *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ default:
+ // Not supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (sec_label_stmt->label != NULL)
+ deparseStringLiteral(str, sec_label_stmt->label);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseCreateForeignTableStmt(StringInfo str, CreateForeignTableStmt *create_foreign_table_stmt)
+{
+ ListCell *lc;
+
+ deparseCreateStmt(str, &create_foreign_table_stmt->base, true);
+
+ appendStringInfoString(str, " SERVER ");
+ appendStringInfoString(str, quote_identifier(create_foreign_table_stmt->servername));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_foreign_table_stmt->options) > 0)
+ deparseAlterGenericOptions(str, create_foreign_table_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseImportForeignSchemaStmt(StringInfo str, ImportForeignSchemaStmt *import_foreign_schema_stmt)
+{
+ appendStringInfoString(str, "IMPORT FOREIGN SCHEMA ");
+
+ appendStringInfoString(str, import_foreign_schema_stmt->remote_schema);
+ appendStringInfoChar(str, ' ');
+
+ switch (import_foreign_schema_stmt->list_type)
+ {
+ case FDW_IMPORT_SCHEMA_ALL:
+ // Default
+ break;
+ case FDW_IMPORT_SCHEMA_LIMIT_TO:
+ appendStringInfoString(str, "LIMIT TO (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ case FDW_IMPORT_SCHEMA_EXCEPT:
+ appendStringInfoString(str, "EXCEPT (");
+ deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
+ appendStringInfoString(str, ") ");
+ break;
+ }
+
+ appendStringInfoString(str, "FROM SERVER ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->server_name));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "INTO ");
+ appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->local_schema));
+ appendStringInfoChar(str, ' ');
+
+ deparseCreateGenericOptions(str, import_foreign_schema_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_table_as_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
+
+ switch (create_table_as_stmt->objtype)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ if (create_table_as_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseIntoClause(str, create_table_as_stmt->into);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "AS ");
+ if (IsA(create_table_as_stmt->query, ExecuteStmt))
+ deparseExecuteStmt(str, castNode(ExecuteStmt, create_table_as_stmt->query));
+ else
+ deparseSelectStmt(str, castNode(SelectStmt, create_table_as_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_as_stmt->into->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (view_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ deparseOptTemp(str, view_stmt->view->relpersistence);
+
+ appendStringInfoString(str, "VIEW ");
+ deparseRangeVar(str, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(view_stmt->aliases) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, view_stmt->aliases);
+ appendStringInfoString(str, ") ");
+ }
+
+ deparseOptWith(str, view_stmt->options);
+
+ appendStringInfoString(str, "AS ");
+ deparseSelectStmt(str, castNode(SelectStmt, view_stmt->query));
+ appendStringInfoChar(str, ' ');
+
+ switch (view_stmt->withCheckOption)
+ {
+ case NO_CHECK_OPTION:
+ // Default
+ break;
+ case LOCAL_CHECK_OPTION:
+ appendStringInfoString(str, "WITH LOCAL CHECK OPTION ");
+ break;
+ case CASCADED_CHECK_OPTION:
+ appendStringInfoString(str, "WITH CHECK OPTION ");
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "DROP ");
+
+ switch (drop_stmt->removeType)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ default:
+ // Other object types are not supported here in the parser
+ Assert(false);
+ }
+
+ if (drop_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (drop_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (drop_stmt->removeType)
+ {
+ // drop_type_any_name
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ deparseAnyNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ // drop_type_name_on_any_name
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseColId(str, strVal(llast(l)));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_CAST:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TRANSFORM:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_LANGUAGE:
+ deparseNameList(str, drop_stmt->objects);
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_AGGREGATE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPERATOR:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseOptDropBehavior(str, drop_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set)
+{
+ switch(grouping_set->kind)
+ {
+ case GROUPING_SET_EMPTY:
+ appendStringInfoString(str, "()");
+ break;
+ case GROUPING_SET_SIMPLE:
+ // Not present in raw parse trees
+ Assert(false);
+ break;
+ case GROUPING_SET_ROLLUP:
+ appendStringInfoString(str, "ROLLUP (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_CUBE:
+ appendStringInfoString(str, "CUBE (");
+ deparseExprList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ case GROUPING_SET_SETS:
+ appendStringInfoString(str, "GROUPING SETS (");
+ deparseGroupByList(str, grouping_set->content);
+ appendStringInfoChar(str, ')');
+ break;
+ }
+}
+
+static void deparseDropTableSpaceStmt(StringInfo str, DropTableSpaceStmt *drop_table_space_stmt)
+{
+ appendStringInfoString(str, "DROP TABLESPACE ");
+
+ if (drop_table_space_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_table_space_stmt->tablespacename);
+}
+
+static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt *alter_object_depends_stmt)
+{
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_depends_stmt->objectType)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ deparseColId(str, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ // No other object types supported here
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (alter_object_depends_stmt->remove)
+ appendStringInfoString(str, "NO ");
+
+ appendStringInfo(str, "DEPENDS ON EXTENSION %s", alter_object_depends_stmt->extname->sval);
+}
+
+static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
+{
+ List *l = NULL;
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_object_schema_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ appendStringInfoString(str, quote_identifier(strVal(alter_object_schema_stmt->object)));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_object_schema_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " SET SCHEMA ");
+ appendStringInfoString(str, quote_identifier(alter_object_schema_stmt->newschema));
+}
+
+static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+ const char *options = NULL;
+ bool trailing_missing_ok = false;
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AddColumn: /* add column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ADD ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ADD COLUMN ");
+ break;
+ case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_ColumnDefault: /* alter column default */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ if (alter_table_cmd->def != NULL)
+ options = "SET DEFAULT";
+ else
+ options = "DROP DEFAULT";
+ break;
+ case AT_CookedColumnDefault: /* add a pre-cooked column default */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropNotNull: /* alter column drop not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP NOT NULL";
+ break;
+ case AT_SetNotNull: /* alter column set not null */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET NOT NULL";
+ break;
+ case AT_DropExpression: /* alter column drop expression */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP EXPRESSION";
+ trailing_missing_ok = true;
+ break;
+ case AT_CheckNotNull: /* check column is already marked not null */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_SetStatistics: /* alter column set statistics */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STATISTICS";
+ break;
+ case AT_SetOptions: /* alter column set ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET";
+ break;
+ case AT_ResetOptions: /* alter column reset ( options ) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "RESET";
+ break;
+ case AT_SetStorage: /* alter column set storage */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET STORAGE";
+ break;
+ case AT_SetCompression: /* alter column set compression */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "SET COMPRESSION";
+ break;
+ case AT_DropColumn: /* drop column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "DROP ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "DROP ");
+ break;
+ case AT_AddIndex: /* add index */
+ appendStringInfoString(str, "ADD INDEX ");
+ break;
+ case AT_ReAddIndex: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddConstraint: /* add constraint */
+ appendStringInfoString(str, "ADD ");
+ break;
+ case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterConstraint: /* alter constraint */
+ appendStringInfoString(str, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
+ break;
+ case AT_ValidateConstraint: /* validate constraint */
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ break;
+ case AT_AddIndexConstraint: /* add constraint using existing index */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropConstraint: /* drop constraint */
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ break;
+ case AT_ReAddComment: /* internal to commands/tablecmds.c */
+ case AT_ReAddStatistics: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterColumnType: /* alter column type */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ appendStringInfoString(str, "ALTER ATTRIBUTE ");
+ else
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "TYPE";
+ break;
+ case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ // Handled via special case in def handling
+ break;
+ case AT_ChangeOwner: /* change owner */
+ appendStringInfoString(str, "OWNER TO ");
+ deparseRoleSpec(str, alter_table_cmd->newowner);
+ break;
+ case AT_ClusterOn: /* CLUSTER ON */
+ appendStringInfoString(str, "CLUSTER ON ");
+ break;
+ case AT_DropCluster: /* SET WITHOUT CLUSTER */
+ appendStringInfoString(str, "SET WITHOUT CLUSTER ");
+ break;
+ case AT_SetLogged: /* SET LOGGED */
+ appendStringInfoString(str, "SET LOGGED ");
+ break;
+ case AT_SetUnLogged: /* SET UNLOGGED */
+ appendStringInfoString(str, "SET UNLOGGED ");
+ break;
+ case AT_DropOids: /* SET WITHOUT OIDS */
+ appendStringInfoString(str, "SET WITHOUT OIDS ");
+ break;
+ case AT_SetTableSpace: /* SET TABLESPACE */
+ appendStringInfoString(str, "SET TABLESPACE ");
+ break;
+ case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
+ appendStringInfoString(str, "SET ");
+ break;
+ case AT_SetAccessMethod:
+ appendStringInfo(str, "SET ACCESS METHOD ");
+ break;
+ case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
+ appendStringInfoString(str, "RESET ");
+ break;
+ case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_EnableTrig: /* ENABLE TRIGGER name */
+ appendStringInfoString(str, "ENABLE TRIGGER ");
+ break;
+ case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
+ appendStringInfoString(str, "ENABLE ALWAYS TRIGGER ");
+ break;
+ case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
+ appendStringInfoString(str, "ENABLE REPLICA TRIGGER ");
+ break;
+ case AT_DisableTrig: /* DISABLE TRIGGER name */
+ appendStringInfoString(str, "DISABLE TRIGGER ");
+ break;
+ case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
+ appendStringInfoString(str, "ENABLE TRIGGER ALL ");
+ break;
+ case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
+ appendStringInfoString(str, "DISABLE TRIGGER ALL ");
+ break;
+ case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
+ appendStringInfoString(str, "ENABLE TRIGGER USER ");
+ break;
+ case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
+ appendStringInfoString(str, "DISABLE TRIGGER USER ");
+ break;
+ case AT_EnableRule: /* ENABLE RULE name */
+ appendStringInfoString(str, "ENABLE RULE ");
+ break;
+ case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
+ appendStringInfoString(str, "ENABLE ALWAYS RULE ");
+ break;
+ case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
+ appendStringInfoString(str, "ENABLE REPLICA RULE ");
+ break;
+ case AT_DisableRule: /* DISABLE RULE name */
+ appendStringInfoString(str, "DISABLE RULE ");
+ break;
+ case AT_AddInherit: /* INHERIT parent */
+ appendStringInfoString(str, "INHERIT ");
+ break;
+ case AT_DropInherit: /* NO INHERIT parent */
+ appendStringInfoString(str, "NO INHERIT ");
+ break;
+ case AT_AddOf: /* OF */
+ appendStringInfoString(str, "OF ");
+ break;
+ case AT_DropOf: /* NOT OF */
+ appendStringInfoString(str, "NOT OF ");
+ break;
+ case AT_ReplicaIdentity: /* REPLICA IDENTITY */
+ appendStringInfoString(str, "REPLICA IDENTITY ");
+ break;
+ case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
+ appendStringInfoString(str, "ENABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
+ appendStringInfoString(str, "DISABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
+ appendStringInfoString(str, "FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
+ appendStringInfoString(str, "NO FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_GenericOptions: /* OPTIONS (...) */
+ // Handled in def field handling
+ break;
+ case AT_AttachPartition: /* ATTACH PARTITION */
+ appendStringInfoString(str, "ATTACH PARTITION ");
+ break;
+ case AT_DetachPartition: /* DETACH PARTITION */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_DetachPartitionFinalize: /* DETACH PARTITION FINALIZE */
+ appendStringInfoString(str, "DETACH PARTITION ");
+ break;
+ case AT_AddIdentity: /* ADD IDENTITY */
+ appendStringInfoString(str, "ALTER ");
+ options = "ADD";
+ // Other details are output via the constraint node (in def field)
+ break;
+ case AT_SetIdentity: /* SET identity column options */
+ appendStringInfoString(str, "ALTER ");
+ break;
+ case AT_DropIdentity: /* DROP IDENTITY */
+ appendStringInfoString(str, "ALTER COLUMN ");
+ options = "DROP IDENTITY";
+ trailing_missing_ok = true;
+ break;
+ }
+
+ if (alter_table_cmd->missing_ok && !trailing_missing_ok)
+ {
+ if (alter_table_cmd->subtype == AT_AddColumn)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+ else
+ appendStringInfoString(str, "IF EXISTS ");
+ }
+
+ if (alter_table_cmd->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(alter_table_cmd->name));
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->num > 0)
+ appendStringInfo(str, "%d ", alter_table_cmd->num);
+
+ if (options != NULL)
+ {
+ appendStringInfoString(str, options);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_table_cmd->missing_ok && trailing_missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_DetachPartitionFinalize:
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
+ appendStringInfoString(str, "FINALIZE ");
+ break;
+ case AT_AddColumn:
+ case AT_AlterColumnType:
+ deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ColumnDefault:
+ if (alter_table_cmd->def != NULL)
+ {
+ deparseExpr(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ }
+ break;
+ case AT_SetStatistics:
+ deparseSignedIconst(str, alter_table_cmd->def);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetOptions:
+ case AT_ResetOptions:
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+ deparseRelOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetStorage:
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetCompression:
+ if (strcmp(strVal(alter_table_cmd->def), "default") == 0)
+ appendStringInfoString(str, "DEFAULT");
+ else
+ deparseColId(str, strVal(alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddIdentity:
+ case AT_AddConstraint:
+ case AT_AlterConstraint:
+ deparseConstraint(str, castNode(Constraint, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_SetIdentity:
+ deparseAlterIdentityColumnOptionList(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AlterColumnGenericOptions:
+ case AT_GenericOptions:
+ deparseAlterGenericOptions(str, castNode(List, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddInherit:
+ case AT_DropInherit:
+ deparseRangeVar(str, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_AddOf:
+ deparseTypeName(str, castNode(TypeName, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ case AT_ReplicaIdentity:
+ deparseReplicaIdentityStmt(str, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(alter_table_cmd->def == NULL);
+ break;
+ }
+
+ deparseOptDropBehavior(str, alter_table_cmd->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static DeparseNodeContext deparseAlterTableObjType(StringInfo str, ObjectType type)
+{
+ switch (type)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ return DEPARSE_NODE_CONTEXT_ALTER_TYPE;
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ return DEPARSE_NODE_CONTEXT_NONE;
+}
+
+static void deparseAlterTableMoveAllStmt(StringInfo str, AlterTableMoveAllStmt *move_all_stmt)
+{
+ appendStringInfoString(str, "ALTER ");
+ deparseAlterTableObjType(str, move_all_stmt->objtype);
+
+ appendStringInfoString(str, "ALL IN TABLESPACE ");
+ appendStringInfoString(str, move_all_stmt->orig_tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (move_all_stmt->roles)
+ {
+ appendStringInfoString(str, "OWNED BY ");
+ deparseRoleList(str, move_all_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "SET TABLESPACE ");
+ appendStringInfoString(str, move_all_stmt->new_tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (move_all_stmt->nowait)
+ {
+ appendStringInfoString(str, "NOWAIT");
+ }
+}
+
+static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+ DeparseNodeContext context = deparseAlterTableObjType(str, alter_table_stmt->objtype);
+
+ if (alter_table_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_table_stmt->relation, context);
+ appendStringInfoChar(str, ' ');
+
+ foreach(lc, alter_table_stmt->cmds)
+ {
+ deparseAlterTableCmd(str, castNode(AlterTableCmd, lfirst(lc)), context);
+ if (lnext(alter_table_stmt->cmds, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterTableSpaceOptionsStmt(StringInfo str, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
+{
+ appendStringInfoString(str, "ALTER TABLESPACE ");
+ deparseColId(str, alter_table_space_options_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_table_space_options_stmt->isReset)
+ appendStringInfoString(str, "RESET ");
+ else
+ appendStringInfoString(str, "SET ");
+
+ deparseRelOptions(str, alter_table_space_options_stmt->options);
+}
+
+static void deparseAlterDomainStmt(StringInfo str, AlterDomainStmt *alter_domain_stmt)
+{
+ appendStringInfoString(str, "ALTER DOMAIN ");
+ deparseAnyName(str, alter_domain_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_domain_stmt->subtype)
+ {
+ case 'T':
+ if (alter_domain_stmt->def != NULL)
+ {
+ appendStringInfoString(str, "SET DEFAULT ");
+ deparseExpr(str, alter_domain_stmt->def);
+ }
+ else
+ {
+ appendStringInfoString(str, "DROP DEFAULT");
+ }
+ break;
+ case 'N':
+ appendStringInfoString(str, "DROP NOT NULL");
+ break;
+ case 'O':
+ appendStringInfoString(str, "SET NOT NULL");
+ break;
+ case 'C':
+ appendStringInfoString(str, "ADD ");
+ deparseConstraint(str, castNode(Constraint, alter_domain_stmt->def));
+ break;
+ case 'X':
+ appendStringInfoString(str, "DROP CONSTRAINT ");
+ if (alter_domain_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ if (alter_domain_stmt->behavior == DROP_CASCADE)
+ appendStringInfoString(str, " CASCADE");
+ break;
+ case 'V':
+ appendStringInfoString(str, "VALIDATE CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
+ break;
+ default:
+ // No other subtypes supported by the parser
+ Assert(false);
+ }
+}
+
+static void deparseRenameStmt(StringInfo str, RenameStmt *rename_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_COLUMN:
+ switch (rename_stmt->relationType)
+ {
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ default:
+ Assert(false);
+ }
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_ATTRIBUTE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (rename_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, rename_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseColId(str, strVal(rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLUMN:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME COLUMN ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME CONSTRAINT ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, quote_identifier(strVal(rename_stmt->object)));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_DOMAIN:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TYPE:
+ deparseAnyName(str, castNode(List, rename_stmt->object));
+ appendStringInfoString(str, " RENAME ");
+ break;
+ case OBJECT_ATTRIBUTE:
+ deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
+ appendStringInfoString(str, " RENAME ATTRIBUTE ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->subname));
+ appendStringInfoChar(str, ' ');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ appendStringInfoString(str, quote_identifier(rename_stmt->newname));
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDropBehavior(str, rename_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_stmt)
+{
+ ListCell *lc;
+ switch (transaction_stmt->kind)
+ {
+ case TRANS_STMT_BEGIN:
+ appendStringInfoString(str, "BEGIN ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_START:
+ appendStringInfoString(str, "START TRANSACTION ");
+ deparseTransactionModeList(str, transaction_stmt->options);
+ break;
+ case TRANS_STMT_COMMIT:
+ appendStringInfoString(str, "COMMIT ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_ROLLBACK:
+ appendStringInfoString(str, "ROLLBACK ");
+ if (transaction_stmt->chain)
+ appendStringInfoString(str, "AND CHAIN ");
+ break;
+ case TRANS_STMT_SAVEPOINT:
+ appendStringInfoString(str, "SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_RELEASE:
+ appendStringInfoString(str, "RELEASE ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_ROLLBACK_TO:
+ appendStringInfoString(str, "ROLLBACK ");
+ appendStringInfoString(str, "TO SAVEPOINT ");
+ appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_PREPARE:
+ appendStringInfoString(str, "PREPARE TRANSACTION ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_COMMIT_PREPARED:
+ appendStringInfoString(str, "COMMIT PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_ROLLBACK_PREPARED:
+ appendStringInfoString(str, "ROLLBACK PREPARED ");
+ deparseStringLiteral(str, transaction_stmt->gid);
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+// Determine if we hit SET TIME ZONE INTERVAL, that has special syntax not
+// supported for other SET statements
+static bool isSetTimeZoneInterval(VariableSetStmt* stmt)
+{
+ if (!(strcmp(stmt->name, "timezone") == 0 &&
+ list_length(stmt->args) == 1 &&
+ IsA(linitial(stmt->args), TypeCast)))
+ return false;
+
+ TypeName* typeName = castNode(TypeCast, linitial(stmt->args))->typeName;
+
+ return (list_length(typeName->names) == 2 &&
+ strcmp(strVal(linitial(typeName->names)), "pg_catalog") == 0 &&
+ strcmp(strVal(llast(typeName->names)), "interval") == 0);
+}
+
+static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
+{
+ ListCell *lc;
+
+ switch (variable_set_stmt->kind)
+ {
+ case VAR_SET_VALUE: /* SET var = value */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ if (isSetTimeZoneInterval(variable_set_stmt))
+ {
+ appendStringInfoString(str, "TIME ZONE ");
+ deparseVarList(str, variable_set_stmt->args);
+ }
+ else
+ {
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO ");
+ deparseVarList(str, variable_set_stmt->args);
+ }
+ break;
+ case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " TO DEFAULT");
+ break;
+ case VAR_SET_CURRENT: /* SET var FROM CURRENT */
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ deparseVarName(str, variable_set_stmt->name);
+ appendStringInfoString(str, " FROM CURRENT");
+ break;
+ case VAR_SET_MULTI: /* special case for SET TRANSACTION ... */
+ Assert(variable_set_stmt->name != NULL);
+ appendStringInfoString(str, "SET ");
+ if (variable_set_stmt->is_local)
+ appendStringInfoString(str, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
+ {
+ appendStringInfoString(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
+ deparseTransactionModeList(str, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
+ {
+ appendStringInfoString(str, "TRANSACTION SNAPSHOT ");
+ deparseStringLiteral(str, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case VAR_RESET: /* RESET var */
+ appendStringInfoString(str, "RESET ");
+ deparseVarName(str, variable_set_stmt->name);
+ break;
+ case VAR_RESET_ALL: /* RESET ALL */
+ appendStringInfoString(str, "RESET ALL");
+ break;
+ }
+}
+
+static void deparseDropdbStmt(StringInfo str, DropdbStmt *dropdb_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "DROP DATABASE ");
+ if (dropdb_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, quote_identifier(dropdb_stmt->dbname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(dropdb_stmt->options) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc, dropdb_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "force") == 0)
+ appendStringInfoString(str, "FORCE");
+ else
+ Assert(false); // Currently there are other supported values
+
+ if (lnext(dropdb_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ if (vacuum_stmt->is_vacuumcmd)
+ appendStringInfoString(str, "VACUUM ");
+ else
+ appendStringInfoString(str, "ANALYZE ");
+
+ deparseUtilityOptionList(str, vacuum_stmt->options);
+
+ foreach(lc, vacuum_stmt->rels)
+ {
+ Assert(IsA(lfirst(lc), VacuumRelation));
+ VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
+
+ deparseRangeVar(str, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(rel->va_cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ foreach(lc2, rel->va_cols)
+ {
+ appendStringInfoString(str, quote_identifier(strVal(lfirst(lc2))));
+ if (lnext(rel->va_cols, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+
+ if (lnext(vacuum_stmt->rels, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseLoadStmt(StringInfo str, LoadStmt *load_stmt)
+{
+ appendStringInfoString(str, "LOAD ");
+ deparseStringLiteral(str, load_stmt->filename);
+}
+
+static void deparseLockStmt(StringInfo str, LockStmt *lock_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "LOCK TABLE ");
+
+ deparseRelationExprList(str, lock_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (lock_stmt->mode != AccessExclusiveLock)
+ {
+ appendStringInfoString(str, "IN ");
+ switch (lock_stmt->mode)
+ {
+ case AccessShareLock:
+ appendStringInfoString(str, "ACCESS SHARE ");
+ break;
+ case RowShareLock:
+ appendStringInfoString(str, "ROW SHARE ");
+ break;
+ case RowExclusiveLock:
+ appendStringInfoString(str, "ROW EXCLUSIVE ");
+ break;
+ case ShareUpdateExclusiveLock:
+ appendStringInfoString(str, "SHARE UPDATE EXCLUSIVE ");
+ break;
+ case ShareLock:
+ appendStringInfoString(str, "SHARE ");
+ break;
+ case ShareRowExclusiveLock:
+ appendStringInfoString(str, "SHARE ROW EXCLUSIVE ");
+ break;
+ case ExclusiveLock:
+ appendStringInfoString(str, "EXCLUSIVE ");
+ break;
+ case AccessExclusiveLock:
+ appendStringInfoString(str, "ACCESS EXCLUSIVE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+ appendStringInfoString(str, "MODE ");
+ }
+
+ if (lock_stmt->nowait)
+ appendStringInfoString(str, "NOWAIT ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseConstraintsSetStmt(StringInfo str, ConstraintsSetStmt *constraints_set_stmt)
+{
+ appendStringInfoString(str, "SET CONSTRAINTS ");
+
+ if (list_length(constraints_set_stmt->constraints) > 0)
+ {
+ deparseQualifiedNameList(str, constraints_set_stmt->constraints);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ if (constraints_set_stmt->deferred)
+ appendStringInfoString(str, "DEFERRED");
+ else
+ appendStringInfoString(str, "IMMEDIATE");
+}
+
+static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ appendStringInfoString(str, "EXPLAIN ");
+
+ deparseUtilityOptionList(str, explain_stmt->options);
+
+ deparseExplainableStmt(str, explain_stmt->query);
+}
+
+static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "COPY ");
+
+ if (copy_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(copy_stmt->attlist) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, copy_stmt->attlist);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (copy_stmt->query != NULL)
+ {
+ appendStringInfoChar(str, '(');
+ deparsePreparableStmt(str, copy_stmt->query);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "FROM ");
+ else
+ appendStringInfoString(str, "TO ");
+
+ if (copy_stmt->is_program)
+ appendStringInfoString(str, "PROGRAM ");
+
+ if (copy_stmt->filename != NULL)
+ {
+ deparseStringLiteral(str, copy_stmt->filename);
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ if (copy_stmt->is_from)
+ appendStringInfoString(str, "STDIN ");
+ else
+ appendStringInfoString(str, "STDOUT ");
+ }
+
+ if (list_length(copy_stmt->options) > 0)
+ {
+ // In some cases, equivalent expressions may have slightly different parse trees for `COPY`
+ // statements. For example the following two statements result in different (but equivalent) parse
+ // trees:
+ //
+ // - COPY foo FROM STDIN CSV FREEZE
+ // - COPY foo FROM STDIN WITH (FORMAT CSV, FREEZE)
+ //
+ // In order to make sure we deparse to the "correct" version, we always try to deparse to the older
+ // compact syntax first.
+ //
+ // The old syntax can be seen here in the Postgres 8.4 Reference:
+ // https://www.postgresql.org/docs/8.4/sql-copy.html
+
+ bool old_fmt = true;
+
+ // Loop over the options to see if any require the new `WITH (...)` syntax.
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
+ {}
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {}
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
+ {}
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
+ {}
+ else
+ {
+ old_fmt = false;
+ break;
+ }
+ }
+
+ // Branch to differing output modes, depending on if we can use the old syntax.
+ if (old_fmt) {
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
+ {
+ appendStringInfoString(str, "FREEZE ");
+ }
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {
+ appendStringInfoString(str, "HEADER ");
+ }
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
+ {
+ appendStringInfoString(str, "CSV ");
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
+ {
+ appendStringInfoString(str, "FORCE QUOTE ");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ // This isn't reachable, the conditions here are exactly the same as the first loop above.
+ Assert(false);
+ }
+ }
+ } else {
+ appendStringInfoString(str, "WITH (");
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "format") == 0)
+ {
+ appendStringInfoString(str, "FORMAT ");
+
+ char *format = strVal(def_elem->arg);
+ if (strcmp(format, "binary") == 0)
+ appendStringInfoString(str, "BINARY");
+ else if (strcmp(format, "csv") == 0)
+ appendStringInfoString(str, "CSV");
+ else if (strcmp(format, "text") == 0)
+ appendStringInfoString(str, "TEXT");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "freeze") == 0)
+ {
+ appendStringInfoString(str, "FREEZE");
+ deparseOptBoolean(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
+ {
+ appendStringInfoString(str, "DELIMITER ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "null") == 0)
+ {
+ appendStringInfoString(str, "NULL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "header") == 0)
+ {
+ appendStringInfoString(str, "HEADER");
+ deparseOptBoolean(str, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "quote") == 0)
+ {
+ appendStringInfoString(str, "QUOTE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "escape") == 0)
+ {
+ appendStringInfoString(str, "ESCAPE ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
+ {
+ appendStringInfoString(str, "FORCE_QUOTE ");
+ if (IsA(def_elem->arg, A_Star))
+ {
+ appendStringInfoChar(str, '*');
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NOT_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "force_null") == 0)
+ {
+ appendStringInfoString(str, "FORCE_NULL (");
+ deparseColumnList(str, castNode(List, def_elem->arg));
+ appendStringInfoChar(str, ')');
+ }
+ else if (strcmp(def_elem->defname, "encoding") == 0)
+ {
+ appendStringInfoString(str, "ENCODING ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL)
+ appendStringInfoChar(str, ' ');
+
+ if (def_elem->arg == NULL)
+ {
+ // Nothing
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ {
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
+ }
+ else if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAStar(str, castNode(A_Star, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoChar(str, '(');
+ foreach(lc2, l)
+ {
+ deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+ }
+
+ if (lnext(copy_stmt->options, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+ }
+
+ deparseWhereClause(str, copy_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDoStmt(StringInfo str, DoStmt *do_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DO ");
+
+ foreach (lc, do_stmt->args)
+ {
+ DefElem *defel = castNode(DefElem, lfirst(lc));
+ if (strcmp(defel->defname, "language") == 0)
+ {
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(defel->arg)));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defel->defname, "as") == 0)
+ {
+ char *strval = strVal(defel->arg);
+ const char *delim = "$$";
+ if (strstr(strval, "$$") != NULL)
+ delim = "$outer$";
+ appendStringInfoString(str, delim);
+ appendStringInfoString(str, strval);
+ appendStringInfoString(str, delim);
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDiscardStmt(StringInfo str, DiscardStmt *discard_stmt)
+{
+ appendStringInfoString(str, "DISCARD ");
+ switch (discard_stmt->target)
+ {
+ case DISCARD_ALL:
+ appendStringInfoString(str, "ALL");
+ break;
+ case DISCARD_PLANS:
+ appendStringInfoString(str, "PLANS");
+ break;
+ case DISCARD_SEQUENCES:
+ appendStringInfoString(str, "SEQUENCES");
+ break;
+ case DISCARD_TEMP:
+ appendStringInfoString(str, "TEMP");
+ break;
+ }
+}
+
+static void deparseDefineStmt(StringInfo str, DefineStmt *define_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (define_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ default:
+ // This shouldn't happen
+ Assert(false);
+ break;
+ }
+
+ if (define_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseFuncName(str, define_stmt->defnames);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAnyOperator(str, define_stmt->defnames);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_COLLATION:
+ deparseAnyName(str, define_stmt->defnames);
+ break;
+ default:
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
+ {
+ deparseAggrArgs(str, define_stmt->args);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (define_stmt->kind == OBJECT_COLLATION &&
+ list_length(define_stmt->definition) == 1 &&
+ strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseAnyName(str, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
+ }
+ else if (list_length(define_stmt->definition) > 0)
+ {
+ deparseDefinition(str, define_stmt->definition);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCompositeTypeStmt(StringInfo str, CompositeTypeStmt *composite_type_stmt)
+{
+ ListCell *lc;
+ RangeVar *typevar;
+
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseRangeVar(str, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
+
+ appendStringInfoString(str, " AS (");
+ foreach(lc, composite_type_stmt->coldeflist)
+ {
+ deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(composite_type_stmt->coldeflist, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateEnumStmt(StringInfo str, CreateEnumStmt *create_enum_stmt)
+{
+ ListCell *lc;
+ appendStringInfoString(str, "CREATE TYPE ");
+
+ deparseAnyName(str, create_enum_stmt->typeName);
+ appendStringInfoString(str, " AS ENUM (");
+ foreach(lc, create_enum_stmt->vals)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(create_enum_stmt->vals, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateRangeStmt(StringInfo str, CreateRangeStmt *create_range_stmt)
+{
+ appendStringInfoString(str, "CREATE TYPE ");
+ deparseAnyName(str, create_range_stmt->typeName);
+ appendStringInfoString(str, " AS RANGE ");
+ deparseDefinition(str, create_range_stmt->params);
+}
+
+static void deparseAlterEnumStmt(StringInfo str, AlterEnumStmt *alter_enum_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_enum_stmt->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->oldVal == NULL)
+ {
+ appendStringInfoString(str, "ADD VALUE ");
+ if (alter_enum_stmt->skipIfNewValExists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_enum_stmt->newValNeighbor)
+ {
+ if (alter_enum_stmt->newValIsAfter)
+ appendStringInfoString(str, "AFTER ");
+ else
+ appendStringInfoString(str, "BEFORE ");
+ deparseStringLiteral(str, alter_enum_stmt->newValNeighbor);
+ }
+ }
+ else
+ {
+ appendStringInfoString(str, "RENAME VALUE ");
+ deparseStringLiteral(str, alter_enum_stmt->oldVal);
+ appendStringInfoString(str, " TO ");
+ deparseStringLiteral(str, alter_enum_stmt->newVal);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionStmt(StringInfo str, AlterExtensionStmt *alter_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_stmt->extname);
+ appendStringInfoString(str, " UPDATE ");
+ foreach (lc, alter_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterExtensionContentsStmt(StringInfo str, AlterExtensionContentsStmt *alter_extension_contents_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER EXTENSION ");
+ deparseColId(str, alter_extension_contents_stmt->extname);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_extension_contents_stmt->action == 1)
+ appendStringInfoString(str, "ADD ");
+ else if (alter_extension_contents_stmt->action == -1)
+ appendStringInfoString(str, "DROP ");
+ else
+ Assert(false);
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ default:
+ // No other object types are supported here in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ // any_name
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_TABLE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ deparseAnyName(str, castNode(List, alter_extension_contents_stmt->object));
+ break;
+ // name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_LANGUAGE:
+ case OBJECT_SCHEMA:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ deparseColId(str, strVal(alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ deparseTypeName(str, castNode(TypeName, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ deparseColId(str, strVal(lsecond(l)));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
+{
+ ListCell *lc;
+
+ if (access_priv->priv_name != NULL)
+ {
+ if (strcmp(access_priv->priv_name, "select") == 0)
+ appendStringInfoString(str, "select");
+ else if (strcmp(access_priv->priv_name, "references") == 0)
+ appendStringInfoString(str, "references");
+ else if (strcmp(access_priv->priv_name, "create") == 0)
+ appendStringInfoString(str, "create");
+ else
+ appendStringInfoString(str, quote_identifier(access_priv->priv_name));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(access_priv->cols) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, access_priv->cols);
+ appendStringInfoChar(str, ')');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
+{
+ ListCell *lc;
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "GRANT OPTION FOR ");
+
+ if (list_length(grant_stmt->privileges) > 0)
+ {
+ foreach(lc, grant_stmt->privileges)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_stmt->privileges, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+
+ appendStringInfoString(str, "ON ");
+
+ deparsePrivilegeTarget(str, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ foreach(lc, grant_stmt->grantees)
+ {
+ deparseRoleSpec(str, castNode(RoleSpec, lfirst(lc)));
+ if (lnext(grant_stmt->grantees, lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_stmt->is_grant && grant_stmt->grant_option)
+ appendStringInfoString(str, "WITH GRANT OPTION ");
+
+ deparseOptDropBehavior(str, grant_stmt->behavior);
+
+ if (grant_stmt->grantor)
+ {
+ appendStringInfoString(str, "GRANTED BY ");
+ deparseRoleSpec(str, castNode(RoleSpec, grant_stmt->grantor));
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
+{
+ ListCell *lc;
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "GRANT ");
+ else
+ appendStringInfoString(str, "REVOKE ");
+
+ if (!grant_role_stmt->is_grant && list_length(grant_role_stmt->opt)) {
+ DefElem *defelem = castNode(DefElem, linitial(grant_role_stmt->opt));
+ Assert(!castNode(Boolean, defelem->arg)->boolval);
+
+ if (strcmp("admin", defelem->defname) == 0) {
+ appendStringInfoString(str, "ADMIN ");
+ } else if (strcmp("inherit", defelem->defname) == 0) {
+ appendStringInfoString(str, "INHERIT ");
+ } else if (strcmp("set", defelem->defname) == 0) {
+ appendStringInfoString(str, "SET ");
+ }
+
+ appendStringInfoString(str, "OPTION FOR ");
+ }
+
+ foreach(lc, grant_role_stmt->granted_roles)
+ {
+ deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_role_stmt->granted_roles, lc))
+ appendStringInfoChar(str, ',');
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (grant_role_stmt->is_grant)
+ appendStringInfoString(str, "TO ");
+ else
+ appendStringInfoString(str, "FROM ");
+
+ deparseRoleList(str, grant_role_stmt->grantee_roles);
+ appendStringInfoChar(str, ' ');
+
+ if (grant_role_stmt->is_grant) {
+ if (list_length(grant_role_stmt->opt) > 0) {
+ appendStringInfoString(str, "WITH ");
+ }
+
+ foreach(lc, grant_role_stmt->opt) {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp("admin", defelem->defname) == 0) {
+ appendStringInfoString(str, "ADMIN ");
+ appendStringInfoString(str, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ } else if (strcmp("inherit", defelem->defname) == 0) {
+ appendStringInfoString(str, "INHERIT ");
+ appendStringInfoString(str, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ } else if (strcmp("set", defelem->defname) == 0) {
+ appendStringInfoString(str, "SET ");
+ appendStringInfoString(str, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ }
+
+ if (lnext(grant_role_stmt->opt, lc)) {
+ appendStringInfoChar(str, ',');
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ if (grant_role_stmt->grantor)
+ {
+ appendStringInfoString(str, "GRANTED BY ");
+ deparseRoleSpec(str, castNode(RoleSpec, grant_role_stmt->grantor));
+ }
+
+ if (grant_role_stmt->behavior == DROP_CASCADE) {
+ appendStringInfoString(str, "CASCADE ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropRoleStmt(StringInfo str, DropRoleStmt *drop_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "DROP ROLE ");
+
+ if (drop_role_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRoleList(str, drop_role_stmt->roles);
+}
+
+static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (index_stmt->unique)
+ appendStringInfoString(str, "UNIQUE ");
+
+ appendStringInfoString(str, "INDEX ");
+
+ if (index_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ if (index_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ if (index_stmt->idxname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(index_stmt->idxname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (index_stmt->accessMethod != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(index_stmt->accessMethod));
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoChar(str, '(');
+ foreach (lc, index_stmt->indexParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+
+ if (list_length(index_stmt->indexIncludingParams) > 0)
+ {
+ appendStringInfoString(str, "INCLUDE (");
+ foreach (lc, index_stmt->indexIncludingParams)
+ {
+ deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexIncludingParams, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoString(str, ") ");
+ }
+
+ if (index_stmt->nulls_not_distinct)
+ {
+ appendStringInfoString(str, "NULLS NOT DISTINCT ");
+ }
+
+ deparseOptWith(str, index_stmt->options);
+
+ if (index_stmt->tableSpace != NULL)
+ {
+ appendStringInfoString(str, "TABLESPACE ");
+ appendStringInfoString(str, quote_identifier(index_stmt->tableSpace));
+ appendStringInfoChar(str, ' ');
+ }
+
+ deparseWhereClause(str, index_stmt->whereClause);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterOpFamilyStmt(StringInfo str, AlterOpFamilyStmt *alter_op_family_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR FAMILY ");
+ deparseAnyName(str, alter_op_family_stmt->opfamilyname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(alter_op_family_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ if (alter_op_family_stmt->isDrop)
+ appendStringInfoString(str, "DROP ");
+ else
+ appendStringInfoString(str, "ADD ");
+
+ deparseOpclassItemList(str, alter_op_family_stmt->items);
+}
+
+static void deparsePrepareStmt(StringInfo str, PrepareStmt *prepare_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "PREPARE ");
+ deparseColId(str, prepare_stmt->name);
+ if (list_length(prepare_stmt->argtypes) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseTypeList(str, prepare_stmt->argtypes);
+ appendStringInfoChar(str, ')');
+ }
+ appendStringInfoString(str, " AS ");
+ deparsePreparableStmt(str, prepare_stmt->query);
+}
+
+static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "EXECUTE ");
+ appendStringInfoString(str, quote_identifier(execute_stmt->name));
+ if (list_length(execute_stmt->params) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, execute_stmt->params);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseDeallocateStmt(StringInfo str, DeallocateStmt *deallocate_stmt)
+{
+ appendStringInfoString(str, "DEALLOCATE ");
+ if (deallocate_stmt->name != NULL)
+ appendStringInfoString(str, quote_identifier(deallocate_stmt->name));
+ else
+ appendStringInfoString(str, "ALL");
+}
+
+// "AlterOptRoleElem" in gram.y
+static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "password") == 0)
+ {
+ appendStringInfoString(str, "PASSWORD ");
+ if (def_elem->arg == NULL)
+ {
+ appendStringInfoString(str, "NULL");
+ }
+ else if (IsA(def_elem->arg, ParamRef))
+ {
+ deparseParamRef(str, castNode(ParamRef, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "connectionlimit") == 0)
+ {
+ appendStringInfo(str, "CONNECTION LIMIT %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validUntil") == 0)
+ {
+ appendStringInfoString(str, "VALID UNTIL ");
+ deparseStringLiteral(str, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "SUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOSUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "CREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOCREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "REPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOREPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "CREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOCREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "LOGIN");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOLOGIN");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "BYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOBYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "INHERIT");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && !boolVal(def_elem->arg))
+ {
+ appendStringInfoString(str, "NOINHERIT");
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "CreateOptRoleElem" in gram.y
+static void deparseCreateRoleElem(StringInfo str, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "sysid") == 0)
+ {
+ appendStringInfo(str, "SYSID %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "adminmembers") == 0)
+ {
+ appendStringInfoString(str, "ADMIN ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "addroleto") == 0)
+ {
+ appendStringInfoString(str, "IN ROLE ");
+ deparseRoleList(str, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ deparseAlterRoleElem(str, def_elem);
+ }
+}
+
+static void deparseCreatePLangStmt(StringInfo str, CreatePLangStmt *create_p_lang_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+
+ if (create_p_lang_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ if (create_p_lang_stmt->pltrusted)
+ appendStringInfoString(str, "TRUSTED ");
+
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(str, create_p_lang_stmt->plname);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_p_lang_stmt->plhandler);
+ appendStringInfoChar(str, ' ');
+
+ if (create_p_lang_stmt->plinline)
+ {
+ appendStringInfoString(str, "INLINE ");
+ deparseHandlerName(str, create_p_lang_stmt->plinline);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_p_lang_stmt->plvalidator)
+ {
+ appendStringInfoString(str, "VALIDATOR ");
+ deparseHandlerName(str, create_p_lang_stmt->plvalidator);
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateRoleStmt(StringInfo str, CreateRoleStmt *create_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ switch (create_role_stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case ROLESTMT_USER:
+ appendStringInfoString(str, "USER ");
+ break;
+ case ROLESTMT_GROUP:
+ appendStringInfoString(str, "GROUP ");
+ break;
+ }
+
+ appendStringInfoString(str, quote_identifier(create_role_stmt->role));
+ appendStringInfoChar(str, ' ');
+
+ if (create_role_stmt->options != NULL)
+ {
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, create_role_stmt->options)
+ {
+ deparseCreateRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterRoleStmt(StringInfo str, AlterRoleStmt *alter_role_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
+ {
+ appendStringInfoString(str, "GROUP ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ if (alter_role_stmt->action == 1)
+ {
+ appendStringInfoString(str, "ADD USER ");
+ }
+ else if (alter_role_stmt->action == -1)
+ {
+ appendStringInfoString(str, "DROP USER ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseRoleList(str, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
+ }
+ else
+ {
+ appendStringInfoString(str, "ROLE ");
+ deparseRoleSpec(str, alter_role_stmt->role);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "WITH ");
+ foreach (lc, alter_role_stmt->options)
+ {
+ deparseAlterRoleElem(str, castNode(DefElem, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDeclareCursorStmt(StringInfo str, DeclareCursorStmt *declare_cursor_stmt)
+{
+ appendStringInfoString(str, "DECLARE ");
+ appendStringInfoString(str, quote_identifier(declare_cursor_stmt->portalname));
+ appendStringInfoChar(str, ' ');
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
+ appendStringInfoString(str, "BINARY ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
+ appendStringInfoString(str, "SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
+ appendStringInfoString(str, "NO SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
+ appendStringInfoString(str, "INSENSITIVE ");
+
+ appendStringInfoString(str, "CURSOR ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
+ appendStringInfoString(str, "WITH HOLD ");
+
+ appendStringInfoString(str, "FOR ");
+
+ deparseSelectStmt(str, castNode(SelectStmt, declare_cursor_stmt->query));
+}
+
+static void deparseFetchStmt(StringInfo str, FetchStmt *fetch_stmt)
+{
+ if (fetch_stmt->ismove)
+ appendStringInfoString(str, "MOVE ");
+ else
+ appendStringInfoString(str, "FETCH ");
+
+ switch (fetch_stmt->direction)
+ {
+ case FETCH_FORWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ // Default
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "FORWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_BACKWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "PRIOR ");
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ appendStringInfoString(str, "BACKWARD ALL ");
+ }
+ else
+ {
+ appendStringInfo(str, "BACKWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_ABSOLUTE:
+ if (fetch_stmt->howMany == 1)
+ {
+ appendStringInfoString(str, "FIRST ");
+ }
+ else if (fetch_stmt->howMany == -1)
+ {
+ appendStringInfoString(str, "LAST ");
+ }
+ else
+ {
+ appendStringInfo(str, "ABSOLUTE %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_RELATIVE:
+ appendStringInfo(str, "RELATIVE %ld ", fetch_stmt->howMany);
+ }
+
+ appendStringInfoString(str, quote_identifier(fetch_stmt->portalname));
+}
+
+static void deparseAlterDefaultPrivilegesStmt(StringInfo str, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER DEFAULT PRIVILEGES ");
+
+ foreach (lc, alter_default_privileges_stmt->options)
+ {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp(defelem->defname, "schemas") == 0)
+ {
+ appendStringInfoString(str, "IN SCHEMA ");
+ deparseNameList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else if (strcmp(defelem->defname, "roles") == 0)
+ {
+ appendStringInfoString(str, "FOR ROLE ");
+ deparseRoleList(str, castNode(List, defelem->arg));
+ appendStringInfoChar(str, ' ');
+ }
+ else
+ {
+ // No other DefElems are supported
+ Assert(false);
+ }
+ }
+
+ deparseGrantStmt(str, alter_default_privileges_stmt->action);
+}
+
+static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
+{
+ appendStringInfoString(str, "REINDEX ");
+
+ deparseUtilityOptionList(str, reindex_stmt->params);
+
+ switch (reindex_stmt->kind)
+ {
+ case REINDEX_OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case REINDEX_OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case REINDEX_OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case REINDEX_OBJECT_SYSTEM:
+ appendStringInfoString(str, "SYSTEM ");
+ break;
+ case REINDEX_OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ }
+
+ if (reindex_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (reindex_stmt->name != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(reindex_stmt->name));
+ }
+}
+
+static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ if (rule_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "RULE ");
+ appendStringInfoString(str, quote_identifier(rule_stmt->rulename));
+ appendStringInfoString(str, " AS ON ");
+
+ switch (rule_stmt->event)
+ {
+ case CMD_UNKNOWN:
+ case CMD_UTILITY:
+ case CMD_NOTHING:
+ // Not supported here
+ Assert(false);
+ break;
+ case CMD_SELECT:
+ appendStringInfoString(str, "SELECT ");
+ break;
+ case CMD_UPDATE:
+ appendStringInfoString(str, "UPDATE ");
+ break;
+ case CMD_INSERT:
+ appendStringInfoString(str, "INSERT ");
+ break;
+ case CMD_DELETE:
+ appendStringInfoString(str, "DELETE ");
+ break;
+ case CMD_MERGE:
+ appendStringInfoString(str, "MERGE ");
+ break;
+ }
+
+ appendStringInfoString(str, "TO ");
+ deparseRangeVar(str, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseWhereClause(str, rule_stmt->whereClause);
+
+ appendStringInfoString(str, "DO ");
+
+ if (rule_stmt->instead)
+ appendStringInfoString(str, "INSTEAD ");
+
+ if (list_length(rule_stmt->actions) == 0)
+ {
+ appendStringInfoString(str, "NOTHING");
+ }
+ else if (list_length(rule_stmt->actions) == 1)
+ {
+ deparseRuleActionStmt(str, linitial(rule_stmt->actions));
+ }
+ else
+ {
+ appendStringInfoChar(str, '(');
+ foreach (lc, rule_stmt->actions)
+ {
+ deparseRuleActionStmt(str, lfirst(lc));
+ if (lnext(rule_stmt->actions, lc))
+ appendStringInfoString(str, "; ");
+ }
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseNotifyStmt(StringInfo str, NotifyStmt *notify_stmt)
+{
+ appendStringInfoString(str, "NOTIFY ");
+ appendStringInfoString(str, quote_identifier(notify_stmt->conditionname));
+
+ if (notify_stmt->payload != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseStringLiteral(str, notify_stmt->payload);
+ }
+}
+
+static void deparseListenStmt(StringInfo str, ListenStmt *listen_stmt)
+{
+ appendStringInfoString(str, "LISTEN ");
+ appendStringInfoString(str, quote_identifier(listen_stmt->conditionname));
+}
+
+static void deparseUnlistenStmt(StringInfo str, UnlistenStmt *unlisten_stmt)
+{
+ appendStringInfoString(str, "UNLISTEN ");
+ if (unlisten_stmt->conditionname == NULL)
+ appendStringInfoString(str, "*");
+ else
+ appendStringInfoString(str, quote_identifier(unlisten_stmt->conditionname));
+}
+
+static void deparseCreateSeqStmt(StringInfo str, CreateSeqStmt *create_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE ");
+
+ deparseOptTemp(str, create_seq_stmt->sequence->relpersistence);
+
+ appendStringInfoString(str, "SEQUENCE ");
+
+ if (create_seq_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseRangeVar(str, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseOptSeqOptList(str, create_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterFunctionStmt(StringInfo str, AlterFunctionStmt *alter_function_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_function_stmt->objtype)
+ {
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ deparseFunctionWithArgtypes(str, alter_function_stmt->func);
+ appendStringInfoChar(str, ' ');
+
+ foreach (lc, alter_function_stmt->actions)
+ {
+ deparseCommonFuncOptItem(str, castNode(DefElem, lfirst(lc)));
+ if (lnext(alter_function_stmt->actions, lc))
+ appendStringInfoChar(str, ' ');
+ }
+}
+
+static void deparseTruncateStmt(StringInfo str, TruncateStmt *truncate_stmt)
+{
+ appendStringInfoString(str, "TRUNCATE ");
+
+ deparseRelationExprList(str, truncate_stmt->relations);
+ appendStringInfoChar(str, ' ');
+
+ if (truncate_stmt->restart_seqs)
+ appendStringInfoString(str, "RESTART IDENTITY ");
+
+ deparseOptDropBehavior(str, truncate_stmt->behavior);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateEventTrigStmt(StringInfo str, CreateEventTrigStmt *create_event_trig_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ appendStringInfoString(str, "CREATE EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "ON ");
+ appendStringInfoString(str, quote_identifier(create_event_trig_stmt->eventname));
+ appendStringInfoChar(str, ' ');
+
+ if (create_event_trig_stmt->whenclause)
+ {
+ appendStringInfoString(str, "WHEN ");
+
+ foreach (lc, create_event_trig_stmt->whenclause)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ List *l = castNode(List, def_elem->arg);
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " IN (");
+ foreach (lc2, l)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+ if (lnext(create_event_trig_stmt->whenclause, lc))
+ appendStringInfoString(str, " AND ");
+ }
+
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_event_trig_stmt->funcname);
+ appendStringInfoString(str, "()");
+}
+
+static void deparseAlterEventTrigStmt(StringInfo str, AlterEventTrigStmt *alter_event_trig_stmt)
+{
+ appendStringInfoString(str, "ALTER EVENT TRIGGER ");
+ appendStringInfoString(str, quote_identifier(alter_event_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_event_trig_stmt->tgenabled)
+ {
+ case TRIGGER_FIRES_ON_ORIGIN:
+ appendStringInfoString(str, "ENABLE");
+ break;
+ case TRIGGER_FIRES_ON_REPLICA:
+ appendStringInfoString(str, "ENABLE REPLICA");
+ break;
+ case TRIGGER_FIRES_ALWAYS:
+ appendStringInfoString(str, "ENABLE ALWAYS");
+ break;
+ case TRIGGER_DISABLED:
+ appendStringInfoString(str, "DISABLE");
+ break;
+ }
+}
+
+static void deparseRefreshMatViewStmt(StringInfo str, RefreshMatViewStmt *refresh_mat_view_stmt)
+{
+ appendStringInfoString(str, "REFRESH MATERIALIZED VIEW ");
+
+ if (refresh_mat_view_stmt->concurrent)
+ appendStringInfoString(str, "CONCURRENTLY ");
+
+ deparseRangeVar(str, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (refresh_mat_view_stmt->skipData)
+ appendStringInfoString(str, "WITH NO DATA ");
+
+ removeTrailingSpace(str);
+}
+
+static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt)
+{
+ switch (replica_identity_stmt->identity_type)
+ {
+ case REPLICA_IDENTITY_NOTHING:
+ appendStringInfoString(str, "NOTHING ");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ appendStringInfoString(str, "FULL ");
+ break;
+ case REPLICA_IDENTITY_DEFAULT:
+ appendStringInfoString(str, "DEFAULT ");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ Assert(replica_identity_stmt->name != NULL);
+ appendStringInfoString(str, "USING INDEX ");
+ appendStringInfoString(str, quote_identifier(replica_identity_stmt->name));
+ break;
+ }
+}
+
+static void deparseCreatePolicyStmt(StringInfo str, CreatePolicyStmt *create_policy_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE POLICY ");
+ deparseColId(str, create_policy_stmt->policy_name);
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (!create_policy_stmt->permissive)
+ appendStringInfoString(str, "AS RESTRICTIVE ");
+
+ if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
+ Assert(true); // Default
+ else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
+ appendStringInfoString(str, "FOR SELECT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
+ appendStringInfoString(str, "FOR INSERT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
+ appendStringInfoString(str, "FOR UPDATE ");
+ else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
+ appendStringInfoString(str, "FOR DELETE ");
+ else
+ Assert(false);
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, create_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ if (create_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, create_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (create_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, create_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseAlterPolicyStmt(StringInfo str, AlterPolicyStmt *alter_policy_stmt)
+{
+ appendStringInfoString(str, "ALTER POLICY ");
+ appendStringInfoString(str, quote_identifier(alter_policy_stmt->policy_name));
+ appendStringInfoString(str, " ON ");
+ deparseRangeVar(str, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_policy_stmt->roles) > 0)
+ {
+ appendStringInfoString(str, "TO ");
+ deparseRoleList(str, alter_policy_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (alter_policy_stmt->qual != NULL)
+ {
+ appendStringInfoString(str, "USING (");
+ deparseExpr(str, alter_policy_stmt->qual);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (alter_policy_stmt->with_check != NULL)
+ {
+ appendStringInfoString(str, "WITH CHECK (");
+ deparseExpr(str, alter_policy_stmt->with_check);
+ appendStringInfoString(str, ") ");
+ }
+}
+
+static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *create_table_space_stmt)
+{
+ appendStringInfoString(str, "CREATE TABLESPACE ");
+ deparseColId(str, create_table_space_stmt->tablespacename);
+ appendStringInfoChar(str, ' ');
+
+ if (create_table_space_stmt->owner != NULL)
+ {
+ appendStringInfoString(str, "OWNER ");
+ deparseRoleSpec(str, create_table_space_stmt->owner);
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, "LOCATION ");
+
+ if (create_table_space_stmt->location != NULL)
+ deparseStringLiteral(str, create_table_space_stmt->location);
+ else
+ appendStringInfoString(str, "''");
+
+ appendStringInfoChar(str, ' ');
+
+ deparseOptWith(str, create_table_space_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateTransformStmt(StringInfo str, CreateTransformStmt *create_transform_stmt)
+{
+ appendStringInfoString(str, "CREATE ");
+ if (create_transform_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+
+ appendStringInfoString(str, "TRANSFORM FOR ");
+ deparseTypeName(str, create_transform_stmt->type_name);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(create_transform_stmt->lang));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoChar(str, '(');
+
+ if (create_transform_stmt->fromsql)
+ {
+ appendStringInfoString(str, "FROM SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->fromsql);
+ }
+
+ if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
+ appendStringInfoString(str, ", ");
+
+ if (create_transform_stmt->tosql)
+ {
+ appendStringInfoString(str, "TO SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(str, create_transform_stmt->tosql);
+ }
+
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
+{
+ appendStringInfoString(str, "CREATE ACCESS METHOD ");
+ appendStringInfoString(str, quote_identifier(create_am_stmt->amname));
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TYPE ");
+ switch (create_am_stmt->amtype)
+ {
+ case AMTYPE_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case AMTYPE_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ }
+
+ appendStringInfoString(str, "HANDLER ");
+ deparseHandlerName(str, create_am_stmt->handler_name);
+}
+
+static void deparsePublicationObjectList(StringInfo str, List *pubobjects) {
+ const ListCell *lc;
+ foreach(lc, pubobjects) {
+ PublicationObjSpec *obj = lfirst(lc);
+
+ switch (obj->pubobjtype) {
+ case PUBLICATIONOBJ_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ deparseRangeVar(str, obj->pubtable->relation, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (obj->pubtable->columns)
+ {
+ appendStringInfoChar(str, '(');
+ deparseColumnList(str, obj->pubtable->columns);
+ appendStringInfoChar(str, ')');
+ }
+
+ if (obj->pubtable->whereClause)
+ {
+ appendStringInfoString(str, " WHERE (");
+ deparseExpr(str, obj->pubtable->whereClause);
+ appendStringInfoString(str, ")");
+ }
+
+ break;
+ case PUBLICATIONOBJ_TABLES_IN_SCHEMA:
+ appendStringInfoString(str, "TABLES IN SCHEMA ");
+ appendStringInfoString(str, quote_identifier(obj->name));
+ break;
+ case PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA:
+ appendStringInfoString(str, "TABLES IN SCHEMA CURRENT_SCHEMA");
+ break;
+ case PUBLICATIONOBJ_CONTINUATION:
+ // This should be unreachable, the parser merges these before we can even get here.
+ Assert(false);
+ break;
+ }
+
+ if (lnext(pubobjects, lc)) {
+ appendStringInfoString(str, ", ");
+ }
+ }
+}
+
+static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "CREATE PUBLICATION ");
+ appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_publication_stmt->pubobjects) > 0)
+ {
+ appendStringInfoString(str, "FOR ");
+ deparsePublicationObjectList(str, create_publication_stmt->pubobjects);
+ appendStringInfoChar(str, ' ');
+ }
+ else if (create_publication_stmt->for_all_tables)
+ {
+ appendStringInfoString(str, "FOR ALL TABLES ");
+ }
+
+ deparseOptDefinition(str, create_publication_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *alter_publication_stmt)
+{
+ appendStringInfoString(str, "ALTER PUBLICATION ");
+ deparseColId(str, alter_publication_stmt->pubname);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(alter_publication_stmt->pubobjects) > 0)
+ {
+ switch (alter_publication_stmt->action)
+ {
+ case AP_SetObjects:
+ appendStringInfoString(str, "SET ");
+ break;
+ case AP_AddObjects:
+ appendStringInfoString(str, "ADD ");
+ break;
+ case AP_DropObjects:
+ appendStringInfoString(str, "DROP ");
+ break;
+ }
+
+ deparsePublicationObjectList(str, alter_publication_stmt->pubobjects);
+ }
+ else if (list_length(alter_publication_stmt->options) > 0)
+ {
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_publication_stmt->options);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+static void deparseAlterSeqStmt(StringInfo str, AlterSeqStmt *alter_seq_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SEQUENCE ");
+
+ if (alter_seq_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseRangeVar(str, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ deparseSeqOptList(str, alter_seq_stmt->options);
+
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSystemStmt(StringInfo str, AlterSystemStmt *alter_system_stmt)
+{
+ appendStringInfoString(str, "ALTER SYSTEM ");
+ deparseVariableSetStmt(str, alter_system_stmt->setstmt);
+}
+
+static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ appendStringInfoString(str, "COMMENT ON ");
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ appendStringInfoString(str, "COLUMN ");
+ break;
+ case OBJECT_INDEX:
+ appendStringInfoString(str, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ appendStringInfoString(str, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ appendStringInfoString(str, "TABLE ");
+ break;
+ case OBJECT_VIEW:
+ appendStringInfoString(str, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ appendStringInfoString(str, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ appendStringInfoString(str, "FOREIGN TABLE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ appendStringInfoString(str, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_ACCESS_METHOD:
+ appendStringInfoString(str, "ACCESS METHOD ");
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ appendStringInfoString(str, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ break;
+ case OBJECT_ROLE:
+ appendStringInfoString(str, "ROLE ");
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ break;
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ break;
+ case OBJECT_TABCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ appendStringInfoString(str, "CONSTRAINT ");
+ break;
+ case OBJECT_POLICY:
+ appendStringInfoString(str, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ appendStringInfoString(str, "RULE ");
+ break;
+ case OBJECT_TRANSFORM:
+ appendStringInfoString(str, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ appendStringInfoString(str, "TRIGGER ");
+ break;
+ case OBJECT_OPCLASS:
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ break;
+ case OBJECT_CAST:
+ appendStringInfoString(str, "CAST ");
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ deparseAnyName(str, castNode(List, comment_stmt->object));
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, quote_identifier(strVal(comment_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ deparseTypeName(str, castNode(TypeName, comment_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON ");
+ deparseAnyNameSkipLast(str, l);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, quote_identifier(strVal(llast(l))));
+ appendStringInfoString(str, " ON DOMAIN ");
+ deparseTypeName(str, linitial(l));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoString(str, "FOR ");
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " LANGUAGE ");
+ appendStringInfoString(str, quote_identifier(strVal(lsecond(l))));
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, comment_stmt->object);
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseValue(str, (union ValUnion *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, comment_stmt->object);
+ appendStringInfoChar(str, '(');
+ deparseTypeName(str, castNode(TypeName, linitial(l)));
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, castNode(TypeName, lsecond(l)));
+ appendStringInfoChar(str, ')');
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ appendStringInfoString(str, " IS ");
+
+ if (comment_stmt->comment != NULL)
+ deparseStringLiteral(str, comment_stmt->comment);
+ else
+ appendStringInfoString(str, "NULL");
+}
+
+static void deparseStatsElem(StringInfo str, StatsElem *stats_elem)
+{
+ // only one of stats_elem->name or stats_elem->expr can be non-null
+ if (stats_elem->name)
+ appendStringInfoString(str, stats_elem->name);
+ else if (stats_elem->expr)
+ {
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, stats_elem->expr);
+ appendStringInfoChar(str, ')');
+ }
+}
+
+static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE STATISTICS ");
+
+ if (create_stats_stmt->if_not_exists)
+ appendStringInfoString(str, "IF NOT EXISTS ");
+
+ deparseAnyName(str, create_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ if (list_length(create_stats_stmt->stat_types) > 0)
+ {
+ appendStringInfoChar(str, '(');
+ deparseNameList(str, create_stats_stmt->stat_types);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ foreach (lc, create_stats_stmt->exprs)
+ {
+ deparseStatsElem(str, lfirst(lc));
+ if (lnext(create_stats_stmt->exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, " FROM ");
+ deparseFromList(str, create_stats_stmt->relations);
+}
+
+static void deparseAlterCollationStmt(StringInfo str, AlterCollationStmt *alter_collation_stmt)
+{
+ appendStringInfoString(str, "ALTER COLLATION ");
+ deparseAnyName(str, alter_collation_stmt->collname);
+ appendStringInfoString(str, " REFRESH VERSION");
+}
+
+static void deparseAlterDatabaseStmt(StringInfo str, AlterDatabaseStmt *alter_database_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseCreatedbOptList(str, alter_database_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterDatabaseSetStmt(StringInfo str, AlterDatabaseSetStmt *alter_database_set_stmt)
+{
+ appendStringInfoString(str, "ALTER DATABASE ");
+ deparseColId(str, alter_database_set_stmt->dbname);
+ appendStringInfoChar(str, ' ');
+ deparseVariableSetStmt(str, alter_database_set_stmt->setstmt);
+}
+
+static void deparseAlterStatsStmt(StringInfo str, AlterStatsStmt *alter_stats_stmt)
+{
+ appendStringInfoString(str, "ALTER STATISTICS ");
+
+ if (alter_stats_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ deparseAnyName(str, alter_stats_stmt->defnames);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfo(str, "SET STATISTICS %d", alter_stats_stmt->stxstattarget);
+}
+
+static void deparseAlterTSDictionaryStmt(StringInfo str, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
+{
+ appendStringInfoString(str, "ALTER TEXT SEARCH DICTIONARY ");
+
+ deparseAnyName(str, alter_ts_dictionary_stmt->dictname);
+ appendStringInfoChar(str, ' ');
+
+ deparseDefinition(str, alter_ts_dictionary_stmt->options);
+}
+
+static void deparseAlterTSConfigurationStmt(StringInfo str, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
+{
+ ListCell *lc = NULL;
+
+ appendStringInfoString(str, "ALTER TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, alter_ts_configuration_stmt->cfgname);
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_ts_configuration_stmt->kind)
+ {
+ case ALTER_TSCONFIG_ADD_MAPPING:
+ appendStringInfoString(str, "ADD MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " WITH ");
+ deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT:
+ appendStringInfoString(str, "ALTER MAPPING REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+ appendStringInfoString(str, "ALTER MAPPING FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ appendStringInfoString(str, " REPLACE ");
+ deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
+ appendStringInfoString(str, " WITH ");
+ deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_DROP_MAPPING:
+ appendStringInfoString(str, "DROP MAPPING ");
+ if (alter_ts_configuration_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+ appendStringInfoString(str, "FOR ");
+ deparseNameList(str, alter_ts_configuration_stmt->tokentype);
+ break;
+ }
+}
+
+static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_show_stmt)
+{
+ appendStringInfoString(str, "SHOW ");
+
+ if (strcmp(variable_show_stmt->name, "timezone") == 0)
+ appendStringInfoString(str, "TIME ZONE");
+ else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
+ appendStringInfoString(str, "TRANSACTION ISOLATION LEVEL");
+ else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
+ appendStringInfoString(str, "SESSION AUTHORIZATION");
+ else if (strcmp(variable_show_stmt->name, "all") == 0)
+ appendStringInfoString(str, "ALL");
+ else
+ appendStringInfoString(str, quote_identifier(variable_show_stmt->name));
+}
+
+static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
+{
+ deparseRangeVar(str, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
+
+ appendStringInfoString(str, " TABLESAMPLE ");
+
+ deparseFuncName(str, range_table_sample->method);
+ appendStringInfoChar(str, '(');
+ deparseExprList(str, range_table_sample->args);
+ appendStringInfoString(str, ") ");
+
+ if (range_table_sample->repeatable != NULL)
+ {
+ appendStringInfoString(str, "REPEATABLE (");
+ deparseExpr(str, range_table_sample->repeatable);
+ appendStringInfoString(str, ") ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseCreateSubscriptionStmt(StringInfo str, CreateSubscriptionStmt *create_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "CREATE SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(create_subscription_stmt->subname));
+
+ appendStringInfoString(str, " CONNECTION ");
+ if (create_subscription_stmt->conninfo != NULL)
+ deparseStringLiteral(str, create_subscription_stmt->conninfo);
+ else
+ appendStringInfoString(str, "''");
+
+ appendStringInfoString(str, " PUBLICATION ");
+
+ foreach(lc, create_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(create_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+
+ deparseOptDefinition(str, create_subscription_stmt->options);
+ removeTrailingSpace(str);
+}
+
+static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *alter_subscription_stmt)
+{
+ ListCell *lc;
+
+ appendStringInfoString(str, "ALTER SUBSCRIPTION ");
+ appendStringInfoString(str, quote_identifier(alter_subscription_stmt->subname));
+ appendStringInfoChar(str, ' ');
+
+ switch (alter_subscription_stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ appendStringInfoString(str, "SET ");
+ deparseDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SKIP:
+ appendStringInfoString(str, "SKIP ");
+ deparseDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ appendStringInfoString(str, "CONNECTION ");
+ deparseStringLiteral(str, alter_subscription_stmt->conninfo);
+ appendStringInfoChar(str, ' ');
+ break;
+ case ALTER_SUBSCRIPTION_REFRESH:
+ appendStringInfoString(str, "REFRESH PUBLICATION ");
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ADD_PUBLICATION:
+ appendStringInfoString(str, "ADD PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_DROP_PUBLICATION:
+ appendStringInfoString(str, "DROP PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SET_PUBLICATION:
+ appendStringInfoString(str, "SET PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(str, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+ deparseOptDefinition(str, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ENABLED:
+ Assert(list_length(alter_subscription_stmt->options) == 1);
+ DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
+ Assert(strcmp(defelem->defname, "enabled") == 0);
+ if (optBooleanValue(defelem->arg))
+ {
+ appendStringInfoString(str, " ENABLE ");
+ }
+ else
+ {
+ appendStringInfoString(str, " DISABLE ");
+ }
+ break;
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseDropSubscriptionStmt(StringInfo str, DropSubscriptionStmt *drop_subscription_stmt)
+{
+ appendStringInfoString(str, "DROP SUBSCRIPTION ");
+
+ if (drop_subscription_stmt->missing_ok)
+ appendStringInfoString(str, "IF EXISTS ");
+
+ appendStringInfoString(str, drop_subscription_stmt->subname);
+}
+
+static void deparseCallStmt(StringInfo str, CallStmt *call_stmt)
+{
+ appendStringInfoString(str, "CALL ");
+ deparseFuncCall(str, call_stmt->funccall);
+}
+
+static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_stmt)
+{
+ List *l = NULL;
+
+ appendStringInfoString(str, "ALTER ");
+
+ switch (alter_owner_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ appendStringInfoString(str, "AGGREGATE ");
+ deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ appendStringInfoString(str, "COLLATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ appendStringInfoString(str, "CONVERSION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ appendStringInfoString(str, "DATABASE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ appendStringInfoString(str, "DOMAIN ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ appendStringInfoString(str, "FUNCTION ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_LANGUAGE:
+ appendStringInfoString(str, "LANGUAGE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ appendStringInfoString(str, "LARGE OBJECT ");
+ deparseNumericOnly(str, (union ValUnion *) alter_owner_stmt->object);
+ break;
+ case OBJECT_OPERATOR:
+ appendStringInfoString(str, "OPERATOR ");
+ deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_owner_stmt->object);
+ appendStringInfoString(str, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(str, l);
+ appendStringInfoString(str, " USING ");
+ deparseColId(str, strVal(linitial(l)));
+ break;
+ case OBJECT_PROCEDURE:
+ appendStringInfoString(str, "PROCEDURE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ appendStringInfoString(str, "ROUTINE ");
+ deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_SCHEMA:
+ appendStringInfoString(str, "SCHEMA ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_TYPE:
+ appendStringInfoString(str, "TYPE ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TABLESPACE:
+ appendStringInfoString(str, "TABLESPACE ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ appendStringInfoString(str, "STATISTICS ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(str, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FDW:
+ appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ appendStringInfoString(str, "SERVER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ appendStringInfoString(str, "EVENT TRIGGER ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_PUBLICATION:
+ appendStringInfoString(str, "PUBLICATION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ appendStringInfoString(str, "SUBSCRIPTION ");
+ deparseColId(str, strVal(alter_owner_stmt->object));
+ break;
+ default:
+ Assert(false);
+ }
+
+ appendStringInfoString(str, " OWNER TO ");
+ deparseRoleSpec(str, alter_owner_stmt->newowner);
+}
+
+// "operator_def_list" in gram.y
+static void deparseOperatorDefList(StringInfo str, List *defs)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, defs)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
+ appendStringInfoString(str, " = ");
+ if (def_elem->arg != NULL)
+ deparseDefArg(str, def_elem->arg, true);
+ else
+ appendStringInfoString(str, "NONE");
+
+ if (lnext(defs, lc))
+ appendStringInfoString(str, ", ");
+ }
+}
+
+static void deparseAlterOperatorStmt(StringInfo str, AlterOperatorStmt *alter_operator_stmt)
+{
+ appendStringInfoString(str, "ALTER OPERATOR ");
+ deparseOperatorWithArgtypes(str, alter_operator_stmt->opername);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_operator_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseAlterTypeStmt(StringInfo str, AlterTypeStmt *alter_type_stmt)
+{
+ appendStringInfoString(str, "ALTER TYPE ");
+ deparseAnyName(str, alter_type_stmt->typeName);
+ appendStringInfoString(str, " SET (");
+ deparseOperatorDefList(str, alter_type_stmt->options);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseDropOwnedStmt(StringInfo str, DropOwnedStmt *drop_owned_stmt)
+{
+ appendStringInfoString(str, "DROP OWNED BY ");
+ deparseRoleList(str, drop_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+ deparseOptDropBehavior(str, drop_owned_stmt->behavior);
+ removeTrailingSpace(str);
+}
+
+static void deparseReassignOwnedStmt(StringInfo str, ReassignOwnedStmt *reassigned_owned_stmt)
+{
+ appendStringInfoString(str, "REASSIGN OWNED BY ");
+
+ deparseRoleList(str, reassigned_owned_stmt->roles);
+ appendStringInfoChar(str, ' ');
+
+ appendStringInfoString(str, "TO ");
+ deparseRoleSpec(str, reassigned_owned_stmt->newrole);
+}
+
+static void deparseClosePortalStmt(StringInfo str, ClosePortalStmt *close_portal_stmt)
+{
+ appendStringInfoString(str, "CLOSE ");
+ if (close_portal_stmt->portalname != NULL)
+ {
+ appendStringInfoString(str, quote_identifier(close_portal_stmt->portalname));
+ }
+ else
+ {
+ appendStringInfoString(str, "ALL");
+ }
+}
+
+static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_stmt)
+{
+ ListCell *lc;
+ bool skip_events_or = true;
+
+ appendStringInfoString(str, "CREATE ");
+ if (create_trig_stmt->replace)
+ appendStringInfoString(str, "OR REPLACE ");
+ if (create_trig_stmt->isconstraint)
+ appendStringInfoString(str, "CONSTRAINT ");
+ appendStringInfoString(str, "TRIGGER ");
+
+ appendStringInfoString(str, quote_identifier(create_trig_stmt->trigname));
+ appendStringInfoChar(str, ' ');
+
+ switch (create_trig_stmt->timing)
+ {
+ case TRIGGER_TYPE_BEFORE:
+ appendStringInfoString(str, "BEFORE ");
+ break;
+ case TRIGGER_TYPE_AFTER:
+ appendStringInfoString(str, "AFTER ");
+ break;
+ case TRIGGER_TYPE_INSTEAD:
+ appendStringInfoString(str, "INSTEAD OF ");
+ break;
+ default:
+ Assert(false);
+ }
+
+ if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
+ {
+ appendStringInfoString(str, "INSERT ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "DELETE ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "UPDATE ");
+ if (list_length(create_trig_stmt->columns) > 0)
+ {
+ appendStringInfoString(str, "OF ");
+ deparseColumnList(str, create_trig_stmt->columns);
+ appendStringInfoChar(str, ' ');
+ }
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ appendStringInfoString(str, "OR ");
+ appendStringInfoString(str, "TRUNCATE ");
+ }
+
+ appendStringInfoString(str, "ON ");
+ deparseRangeVar(str, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+
+ if (create_trig_stmt->transitionRels != NULL)
+ {
+ appendStringInfoString(str, "REFERENCING ");
+ foreach(lc, create_trig_stmt->transitionRels)
+ {
+ deparseTriggerTransition(str, castNode(TriggerTransition, lfirst(lc)));
+ appendStringInfoChar(str, ' ');
+ }
+ }
+
+ if (create_trig_stmt->constrrel != NULL)
+ {
+ appendStringInfoString(str, "FROM ");
+ deparseRangeVar(str, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (create_trig_stmt->deferrable)
+ appendStringInfoString(str, "DEFERRABLE ");
+
+ if (create_trig_stmt->initdeferred)
+ appendStringInfoString(str, "INITIALLY DEFERRED ");
+
+ if (create_trig_stmt->row)
+ appendStringInfoString(str, "FOR EACH ROW ");
+
+ if (create_trig_stmt->whenClause)
+ {
+ appendStringInfoString(str, "WHEN (");
+ deparseExpr(str, create_trig_stmt->whenClause);
+ appendStringInfoString(str, ") ");
+ }
+
+ appendStringInfoString(str, "EXECUTE FUNCTION ");
+ deparseFuncName(str, create_trig_stmt->funcname);
+ appendStringInfoChar(str, '(');
+ foreach(lc, create_trig_stmt->args)
+ {
+ deparseStringLiteral(str, strVal(lfirst(lc)));
+ if (lnext(create_trig_stmt->args, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition)
+{
+ if (trigger_transition->isNew)
+ appendStringInfoString(str, "NEW ");
+ else
+ appendStringInfoString(str, "OLD ");
+
+ if (trigger_transition->isTable)
+ appendStringInfoString(str, "TABLE ");
+ else
+ appendStringInfoString(str, "ROW ");
+
+ appendStringInfoString(str, quote_identifier(trigger_transition->name));
+}
+
+static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
+{
+ switch (xml_expr->op)
+ {
+ case IS_XMLCONCAT: /* XMLCONCAT(args) */
+ appendStringInfoString(str, "xmlconcat(");
+ deparseExprList(str, xml_expr->args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
+ appendStringInfoString(str, "xmlelement(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->named_args != NULL)
+ {
+ appendStringInfoString(str, ", xmlattributes(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoString(str, ")");
+ }
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExprList(str, xml_expr->args);
+ }
+ appendStringInfoString(str, ")");
+ break;
+ case IS_XMLFOREST: /* XMLFOREST(xml_attributes) */
+ appendStringInfoString(str, "xmlforest(");
+ deparseXmlAttributeList(str, xml_expr->named_args);
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
+ Assert(list_length(xml_expr->args) == 2);
+ appendStringInfoString(str, "xmlparse(");
+ switch (xml_expr->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLPI: /* XMLPI(name [, args]) */
+ appendStringInfoString(str, "xmlpi(name ");
+ appendStringInfoString(str, quote_identifier(xml_expr->name));
+ if (xml_expr->args != NULL)
+ {
+ appendStringInfoString(str, ", ");
+ deparseExpr(str, linitial(xml_expr->args));
+ }
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
+ appendStringInfoString(str, "xmlroot(");
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, ", version ");
+ if (castNode(A_Const, lsecond(xml_expr->args))->isnull)
+ appendStringInfoString(str, "NO VALUE");
+ else
+ deparseExpr(str, lsecond(xml_expr->args));
+ if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
+ appendStringInfoString(str, ", STANDALONE YES");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
+ appendStringInfoString(str, ", STANDALONE NO");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
+ appendStringInfoString(str, ", STANDALONE NO VALUE");
+ appendStringInfoChar(str, ')');
+ break;
+ case IS_XMLSERIALIZE: /* XMLSERIALIZE(is_document, xmlval) */
+ // These are represented as XmlSerialize in raw parse trees
+ Assert(false);
+ break;
+ case IS_DOCUMENT: /* xmlval IS DOCUMENT */
+ Assert(list_length(xml_expr->args) == 1);
+ deparseExpr(str, linitial(xml_expr->args));
+ appendStringInfoString(str, " IS DOCUMENT");
+ break;
+ }
+}
+
+static void deparseRangeTableFuncCol(StringInfo str, RangeTableFuncCol* range_table_func_col)
+{
+ appendStringInfoString(str, quote_identifier(range_table_func_col->colname));
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->for_ordinality)
+ {
+ appendStringInfoString(str, "FOR ORDINALITY ");
+ }
+ else
+ {
+ deparseTypeName(str, range_table_func_col->typeName);
+ appendStringInfoChar(str, ' ');
+
+ if (range_table_func_col->colexpr)
+ {
+ appendStringInfoString(str, "PATH ");
+ deparseExpr(str, range_table_func_col->colexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->coldefexpr)
+ {
+ appendStringInfoString(str, "DEFAULT ");
+ deparseExpr(str, range_table_func_col->coldefexpr);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (range_table_func_col->is_not_null)
+ appendStringInfoString(str, "NOT NULL ");
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func)
+{
+ ListCell *lc;
+
+ if (range_table_func->lateral)
+ appendStringInfoString(str, "LATERAL ");
+
+ appendStringInfoString(str, "xmltable(");
+ if (range_table_func->namespaces)
+ {
+ appendStringInfoString(str, "xmlnamespaces(");
+ deparseXmlNamespaceList(str, range_table_func->namespaces);
+ appendStringInfoString(str, "), ");
+ }
+
+ appendStringInfoChar(str, '(');
+ deparseExpr(str, range_table_func->rowexpr);
+ appendStringInfoChar(str, ')');
+
+ appendStringInfoString(str, " PASSING ");
+ deparseExpr(str, range_table_func->docexpr);
+
+ appendStringInfoString(str, " COLUMNS ");
+ foreach(lc, range_table_func->columns)
+ {
+ deparseRangeTableFuncCol(str, castNode(RangeTableFuncCol, lfirst(lc)));
+ if (lnext(range_table_func->columns, lc))
+ appendStringInfoString(str, ", ");
+ }
+
+ appendStringInfoString(str, ") ");
+
+ if (range_table_func->alias)
+ {
+ appendStringInfoString(str, "AS ");
+ deparseAlias(str, range_table_func->alias);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize)
+{
+ appendStringInfoString(str, "xmlserialize(");
+ switch (xml_serialize->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ appendStringInfoString(str, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ appendStringInfoString(str, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(str, xml_serialize->expr);
+ appendStringInfoString(str, " AS ");
+ deparseTypeName(str, xml_serialize->typeName);
+
+ if (xml_serialize->indent) {
+ appendStringInfoString(str, " INDENT");
+ }
+
+ appendStringInfoString(str, ")");
+}
+
+static void deparseJsonFormat(StringInfo str, JsonFormat *json_format)
+{
+ if (json_format == NULL || json_format->format_type == JS_FORMAT_DEFAULT)
+ return;
+
+ appendStringInfoString(str, "FORMAT JSON ");
+
+ switch (json_format->encoding)
+ {
+ case JS_ENC_UTF8:
+ appendStringInfoString(str, "ENCODING utf8 ");
+ break;
+ case JS_ENC_UTF16:
+ appendStringInfoString(str, "ENCODING utf16 ");
+ break;
+ case JS_ENC_UTF32:
+ appendStringInfoString(str, "ENCODING utf32 ");
+ break;
+ case JS_ENC_DEFAULT:
+ // no encoding specified
+ break;
+ }
+}
+
+static void deparseJsonIsPredicate(StringInfo str, JsonIsPredicate *j)
+{
+ deparseExpr(str, j->expr);
+ appendStringInfoChar(str, ' ');
+
+ deparseJsonFormat(str, castNode(JsonFormat, j->format));
+
+ appendStringInfoString(str, "IS ");
+
+ switch (j->item_type)
+ {
+ case JS_TYPE_ANY:
+ appendStringInfoString(str, "JSON ");
+ break;
+ case JS_TYPE_ARRAY:
+ appendStringInfoString(str, "JSON ARRAY ");
+ break;
+ case JS_TYPE_OBJECT:
+ appendStringInfoString(str, "JSON OBJECT ");
+ break;
+ case JS_TYPE_SCALAR:
+ appendStringInfoString(str, "JSON SCALAR ");
+ break;
+ }
+
+ if (j->unique_keys)
+ appendStringInfoString(str, "WITH UNIQUE ");
+
+ removeTrailingSpace(str);
+}
+
+// "json_value_expr" in gram.y
+static void deparseJsonValueExpr(StringInfo str, JsonValueExpr *json_value_expr)
+{
+ deparseExpr(str, (Node *) json_value_expr->raw_expr);
+ appendStringInfoChar(str, ' ');
+ deparseJsonFormat(str, json_value_expr->format);
+}
+
+// "json_value_expr_list" in gram.y
+static void deparseJsonValueExprList(StringInfo str, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseJsonValueExpr(str, lfirst(lc));
+ removeTrailingSpace(str);
+ if (lnext(exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+}
+
+// "json_name_and_value" in gram.y
+static void deparseJsonKeyValue(StringInfo str, JsonKeyValue *json_key_value)
+{
+ deparseExpr(str, (Node *) json_key_value->key);
+ appendStringInfoString(str, ": ");
+ deparseJsonValueExpr(str, json_key_value->value);
+}
+
+// "json_name_and_value_list" in gram.y
+static void deparseJsonKeyValueList(StringInfo str, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseJsonKeyValue(str, lfirst(lc));
+ removeTrailingSpace(str);
+ if (lnext(exprs, lc))
+ appendStringInfoString(str, ", ");
+ }
+ appendStringInfoChar(str, ' ');
+}
+
+static void deparseJsonOutput(StringInfo str, JsonOutput *json_output)
+{
+ if (json_output == NULL)
+ return;
+
+ Assert(json_output->returning != NULL);
+
+ appendStringInfoString(str, "RETURNING ");
+ deparseTypeName(str, json_output->typeName);
+ appendStringInfoChar(str, ' ');
+ deparseJsonFormat(str, json_output->returning->format);
+}
+
+static void deparseJsonObjectAgg(StringInfo str, JsonObjectAgg *json_object_agg)
+{
+ Assert(json_object_agg->constructor != NULL);
+
+ appendStringInfoString(str, "JSON_OBJECTAGG(");
+ deparseJsonKeyValue(str, json_object_agg->arg);
+
+ if (json_object_agg->absent_on_null)
+ appendStringInfoString(str, "ABSENT ON NULL ");
+
+ if (json_object_agg->unique)
+ appendStringInfoString(str, "WITH UNIQUE ");
+
+ deparseJsonOutput(str, json_object_agg->constructor->output);
+
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+
+ if (json_object_agg->constructor->agg_filter)
+ {
+ appendStringInfoString(str, "FILTER (WHERE ");
+ deparseExpr(str, json_object_agg->constructor->agg_filter);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (json_object_agg->constructor->over)
+ {
+ struct WindowDef *over = json_object_agg->constructor->over;
+ appendStringInfoString(str, "OVER ");
+ if (over->name)
+ appendStringInfoString(str, over->name);
+ else
+ deparseWindowDef(str, over);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseJsonArrayAgg(StringInfo str, JsonArrayAgg *json_array_agg)
+{
+ Assert(json_array_agg->constructor != NULL);
+
+ appendStringInfoString(str, "JSON_ARRAYAGG(");
+ deparseJsonValueExpr(str, json_array_agg->arg);
+ deparseOptSortClause(str, json_array_agg->constructor->agg_order);
+
+ if (!json_array_agg->absent_on_null)
+ appendStringInfoString(str, "NULL ON NULL ");
+
+ deparseJsonOutput(str, json_array_agg->constructor->output);
+
+ removeTrailingSpace(str);
+ appendStringInfoString(str, ") ");
+
+ if (json_array_agg->constructor->agg_filter)
+ {
+ appendStringInfoString(str, "FILTER (WHERE ");
+ deparseExpr(str, json_array_agg->constructor->agg_filter);
+ appendStringInfoString(str, ") ");
+ }
+
+ if (json_array_agg->constructor->over)
+ {
+ struct WindowDef *over = json_array_agg->constructor->over;
+ appendStringInfoString(str, "OVER ");
+ if (over->name)
+ appendStringInfoString(str, over->name);
+ else
+ deparseWindowDef(str, over);
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseJsonObjectConstructor(StringInfo str, JsonObjectConstructor *json_object_constructor)
+{
+ appendStringInfoString(str, "JSON_OBJECT(");
+ deparseJsonKeyValueList(str, json_object_constructor->exprs);
+
+ if (json_object_constructor->absent_on_null)
+ appendStringInfoString(str, "ABSENT ON NULL ");
+
+ if (json_object_constructor->unique)
+ appendStringInfoString(str, "WITH UNIQUE ");
+
+ deparseJsonOutput(str, json_object_constructor->output);
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseJsonArrayConstructor(StringInfo str, JsonArrayConstructor *json_array_constructor)
+{
+ appendStringInfoString(str, "JSON_ARRAY(");
+ deparseJsonValueExprList(str, json_array_constructor->exprs);
+
+ if (!json_array_constructor->absent_on_null)
+ appendStringInfoString(str, "NULL ON NULL ");
+
+ deparseJsonOutput(str, json_array_constructor->output);
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseJsonArrayQueryConstructor(StringInfo str, JsonArrayQueryConstructor *json_array_query_constructor)
+{
+ appendStringInfoString(str, "JSON_ARRAY(");
+
+ deparseSelectStmt(str, castNode(SelectStmt, json_array_query_constructor->query));
+ deparseJsonFormat(str, json_array_query_constructor->format);
+ deparseJsonOutput(str, json_array_query_constructor->output);
+
+ removeTrailingSpace(str);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
+{
+ appendStringInfoString(str, "GROUPING(");
+ deparseExprList(str, grouping_func->args);
+ appendStringInfoChar(str, ')');
+}
+
+static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
+{
+ appendStringInfoString(str, "CLUSTER ");
+
+ deparseUtilityOptionList(str, cluster_stmt->params);
+
+ if (cluster_stmt->relation != NULL)
+ {
+ deparseRangeVar(str, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ appendStringInfoChar(str, ' ');
+ }
+
+ if (cluster_stmt->indexname != NULL)
+ {
+ appendStringInfoString(str, "USING ");
+ appendStringInfoString(str, quote_identifier(cluster_stmt->indexname));
+ appendStringInfoChar(str, ' ');
+ }
+
+ removeTrailingSpace(str);
+}
+
+static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context)
+{
+ if (!value) {
+ appendStringInfoString(str, "NULL");
+ return;
+ }
+
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ case T_Float:
+ deparseNumericOnly(str, value);
+ break;
+ case T_Boolean:
+ appendStringInfoString(str, value->boolval.boolval ? "true" : "false");
+ break;
+ case T_String:
+ if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
+ appendStringInfoString(str, quote_identifier(value->sval.sval));
+ } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
+ deparseStringLiteral(str, value->sval.sval);
+ } else {
+ appendStringInfoString(str, value->sval.sval);
+ }
+ break;
+ case T_BitString:
+ if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'x')
+ {
+ appendStringInfoChar(str, 'x');
+ deparseStringLiteral(str, value->sval.sval + 1);
+ }
+ else if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'b')
+ {
+ appendStringInfoChar(str, 'b');
+ deparseStringLiteral(str, value->sval.sval + 1);
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ default:
+ elog(ERROR, "deparse: unrecognized value node type: %d",
+ (int) nodeTag(value));
+ break;
+ }
+}
+
+// "PrepareableStmt" in gram.y
+static void deparsePreparableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(str, castNode(MergeStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "RuleActionStmt" in gram.y
+static void deparseRuleActionStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "ExplainableStmt" in gram.y
+static void deparseExplainableStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_CreateTableAsStmt:
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(str, castNode(MergeStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "schema_stmt" in gram.y
+static void deparseSchemaStmt(StringInfo str, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "stmt" in gram.y
+static void deparseStmt(StringInfo str, Node *node)
+{
+ // Note the following grammar names are missing in the list, because they
+ // get mapped to other node types:
+ //
+ // - AlterForeignTableStmt (=> AlterTableStmt)
+ // - AlterGroupStmt (=> AlterRoleStmt)
+ // - AlterCompositeTypeStmt (=> AlterTableStmt)
+ // - AnalyzeStmt (=> VacuumStmt)
+ // - CreateGroupStmt (=> CreateRoleStmt)
+ // - CreateMatViewStmt (=> CreateTableAsStmt)
+ // - CreateUserStmt (=> CreateRoleStmt)
+ // - DropCastStmt (=> DropStmt)
+ // - DropOpClassStmt (=> DropStmt)
+ // - DropOpFamilyStmt (=> DropStmt)
+ // - DropPLangStmt (=> DropPLangStmt)
+ // - DropTransformStmt (=> DropStmt)
+ // - RemoveAggrStmt (=> DropStmt)
+ // - RemoveFuncStmt (=> DropStmt)
+ // - RemoveOperStmt (=> DropStmt)
+ // - RevokeStmt (=> GrantStmt)
+ // - RevokeRoleStmt (=> GrantRoleStmt)
+ // - VariableResetStmt (=> VariableSetStmt)
+ //
+ // And the following grammar names error out in the parser:
+ // - CreateAssertionStmt (not supported yet)
+ switch (nodeTag(node))
+ {
+ case T_AlterEventTrigStmt:
+ deparseAlterEventTrigStmt(str, castNode(AlterEventTrigStmt, node));
+ break;
+ case T_AlterCollationStmt:
+ deparseAlterCollationStmt(str, castNode(AlterCollationStmt, node));
+ break;
+ case T_AlterDatabaseStmt:
+ deparseAlterDatabaseStmt(str, castNode(AlterDatabaseStmt, node));
+ break;
+ case T_AlterDatabaseSetStmt:
+ deparseAlterDatabaseSetStmt(str, castNode(AlterDatabaseSetStmt, node));
+ break;
+ case T_AlterDefaultPrivilegesStmt:
+ deparseAlterDefaultPrivilegesStmt(str, castNode(AlterDefaultPrivilegesStmt, node));
+ break;
+ case T_AlterDomainStmt:
+ deparseAlterDomainStmt(str, castNode(AlterDomainStmt, node));
+ break;
+ case T_AlterEnumStmt:
+ deparseAlterEnumStmt(str, castNode(AlterEnumStmt, node));
+ break;
+ case T_AlterExtensionStmt:
+ deparseAlterExtensionStmt(str, castNode(AlterExtensionStmt, node));
+ break;
+ case T_AlterExtensionContentsStmt:
+ deparseAlterExtensionContentsStmt(str, castNode(AlterExtensionContentsStmt, node));
+ break;
+ case T_AlterFdwStmt:
+ deparseAlterFdwStmt(str, castNode(AlterFdwStmt, node));
+ break;
+ case T_AlterForeignServerStmt:
+ deparseAlterForeignServerStmt(str, castNode(AlterForeignServerStmt, node));
+ break;
+ case T_AlterFunctionStmt:
+ deparseAlterFunctionStmt(str, castNode(AlterFunctionStmt, node));
+ break;
+ case T_AlterObjectDependsStmt:
+ deparseAlterObjectDependsStmt(str, castNode(AlterObjectDependsStmt, node));
+ break;
+ case T_AlterObjectSchemaStmt:
+ deparseAlterObjectSchemaStmt(str, castNode(AlterObjectSchemaStmt, node));
+ break;
+ case T_AlterOwnerStmt:
+ deparseAlterOwnerStmt(str, castNode(AlterOwnerStmt, node));
+ break;
+ case T_AlterOperatorStmt:
+ deparseAlterOperatorStmt(str, castNode(AlterOperatorStmt, node));
+ break;
+ case T_AlterTypeStmt:
+ deparseAlterTypeStmt(str, castNode(AlterTypeStmt, node));
+ break;
+ case T_AlterPolicyStmt:
+ deparseAlterPolicyStmt(str, castNode(AlterPolicyStmt, node));
+ break;
+ case T_AlterSeqStmt:
+ deparseAlterSeqStmt(str, castNode(AlterSeqStmt, node));
+ break;
+ case T_AlterSystemStmt:
+ deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
+ break;
+ case T_AlterTableMoveAllStmt:
+ deparseAlterTableMoveAllStmt(str, castNode(AlterTableMoveAllStmt, node));
+ break;
+ case T_AlterTableStmt:
+ deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
+ break;
+ case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
+ deparseAlterTableSpaceOptionsStmt(str, castNode(AlterTableSpaceOptionsStmt, node));
+ break;
+ case T_AlterPublicationStmt:
+ deparseAlterPublicationStmt(str, castNode(AlterPublicationStmt, node));
+ break;
+ case T_AlterRoleSetStmt:
+ deparseAlterRoleSetStmt(str, castNode(AlterRoleSetStmt, node));
+ break;
+ case T_AlterRoleStmt:
+ deparseAlterRoleStmt(str, castNode(AlterRoleStmt, node));
+ break;
+ case T_AlterSubscriptionStmt:
+ deparseAlterSubscriptionStmt(str, castNode(AlterSubscriptionStmt, node));
+ break;
+ case T_AlterStatsStmt:
+ deparseAlterStatsStmt(str, castNode(AlterStatsStmt, node));
+ break;
+ case T_AlterTSConfigurationStmt:
+ deparseAlterTSConfigurationStmt(str, castNode(AlterTSConfigurationStmt, node));
+ break;
+ case T_AlterTSDictionaryStmt:
+ deparseAlterTSDictionaryStmt(str, castNode(AlterTSDictionaryStmt, node));
+ break;
+ case T_AlterUserMappingStmt:
+ deparseAlterUserMappingStmt(str, castNode(AlterUserMappingStmt, node));
+ break;
+ case T_CallStmt:
+ deparseCallStmt(str, castNode(CallStmt, node));
+ break;
+ case T_CheckPointStmt:
+ deparseCheckPointStmt(str, castNode(CheckPointStmt, node));
+ break;
+ case T_ClosePortalStmt:
+ deparseClosePortalStmt(str, castNode(ClosePortalStmt, node));
+ break;
+ case T_ClusterStmt:
+ deparseClusterStmt(str, castNode(ClusterStmt, node));
+ break;
+ case T_CommentStmt:
+ deparseCommentStmt(str, castNode(CommentStmt, node));
+ break;
+ case T_ConstraintsSetStmt:
+ deparseConstraintsSetStmt(str, castNode(ConstraintsSetStmt, node));
+ break;
+ case T_CopyStmt:
+ deparseCopyStmt(str, castNode(CopyStmt, node));
+ break;
+ case T_CreateAmStmt:
+ deparseCreateAmStmt(str, castNode(CreateAmStmt, node));
+ break;
+ case T_CreateTableAsStmt: // "CreateAsStmt" in gram.y
+ deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
+ break;
+ case T_CreateCastStmt:
+ deparseCreateCastStmt(str, castNode(CreateCastStmt, node));
+ break;
+ case T_CreateConversionStmt:
+ deparseCreateConversionStmt(str, castNode(CreateConversionStmt, node));
+ break;
+ case T_CreateDomainStmt:
+ deparseCreateDomainStmt(str, castNode(CreateDomainStmt, node));
+ break;
+ case T_CreateExtensionStmt:
+ deparseCreateExtensionStmt(str, castNode(CreateExtensionStmt, node));
+ break;
+ case T_CreateFdwStmt:
+ deparseCreateFdwStmt(str, castNode(CreateFdwStmt, node));
+ break;
+ case T_CreateForeignServerStmt:
+ deparseCreateForeignServerStmt(str, castNode(CreateForeignServerStmt, node));
+ break;
+ case T_CreateForeignTableStmt:
+ deparseCreateForeignTableStmt(str, castNode(CreateForeignTableStmt, node));
+ break;
+ case T_CreateFunctionStmt:
+ deparseCreateFunctionStmt(str, castNode(CreateFunctionStmt, node));
+ break;
+ case T_CreateOpClassStmt:
+ deparseCreateOpClassStmt(str, castNode(CreateOpClassStmt, node));
+ break;
+ case T_CreateOpFamilyStmt:
+ deparseCreateOpFamilyStmt(str, castNode(CreateOpFamilyStmt, node));
+ break;
+ case T_CreatePublicationStmt:
+ deparseCreatePublicationStmt(str, castNode(CreatePublicationStmt, node));
+ break;
+ case T_AlterOpFamilyStmt:
+ deparseAlterOpFamilyStmt(str, castNode(AlterOpFamilyStmt, node));
+ break;
+ case T_CreatePolicyStmt:
+ deparseCreatePolicyStmt(str, castNode(CreatePolicyStmt, node));
+ break;
+ case T_CreatePLangStmt:
+ deparseCreatePLangStmt(str, castNode(CreatePLangStmt, node));
+ break;
+ case T_CreateSchemaStmt:
+ deparseCreateSchemaStmt(str, castNode(CreateSchemaStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateStmt:
+ deparseCreateStmt(str, castNode(CreateStmt, node), false);
+ break;
+ case T_CreateSubscriptionStmt:
+ deparseCreateSubscriptionStmt(str, castNode(CreateSubscriptionStmt, node));
+ break;
+ case T_CreateStatsStmt:
+ deparseCreateStatsStmt(str, castNode(CreateStatsStmt, node));
+ break;
+ case T_CreateTableSpaceStmt:
+ deparseCreateTableSpaceStmt(str, castNode(CreateTableSpaceStmt, node));
+ break;
+ case T_CreateTransformStmt:
+ deparseCreateTransformStmt(str, castNode(CreateTransformStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
+ break;
+ case T_CreateEventTrigStmt:
+ deparseCreateEventTrigStmt(str, castNode(CreateEventTrigStmt, node));
+ break;
+ case T_CreateRoleStmt:
+ deparseCreateRoleStmt(str, castNode(CreateRoleStmt, node));
+ break;
+ case T_CreateUserMappingStmt:
+ deparseCreateUserMappingStmt(str, castNode(CreateUserMappingStmt, node));
+ break;
+ case T_CreatedbStmt:
+ deparseCreatedbStmt(str, castNode(CreatedbStmt, node));
+ break;
+ case T_DeallocateStmt:
+ deparseDeallocateStmt(str, castNode(DeallocateStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
+ break;
+ case T_DefineStmt:
+ deparseDefineStmt(str, castNode(DefineStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(str, castNode(DeleteStmt, node));
+ break;
+ case T_DiscardStmt:
+ deparseDiscardStmt(str, castNode(DiscardStmt, node));
+ break;
+ case T_DoStmt:
+ deparseDoStmt(str, castNode(DoStmt, node));
+ break;
+ case T_DropOwnedStmt:
+ deparseDropOwnedStmt(str, castNode(DropOwnedStmt, node));
+ break;
+ case T_DropStmt:
+ deparseDropStmt(str, castNode(DropStmt, node));
+ break;
+ case T_DropSubscriptionStmt:
+ deparseDropSubscriptionStmt(str, castNode(DropSubscriptionStmt, node));
+ break;
+ case T_DropTableSpaceStmt:
+ deparseDropTableSpaceStmt(str, castNode(DropTableSpaceStmt, node));
+ break;
+ case T_DropRoleStmt:
+ deparseDropRoleStmt(str, castNode(DropRoleStmt, node));
+ break;
+ case T_DropUserMappingStmt:
+ deparseDropUserMappingStmt(str, castNode(DropUserMappingStmt, node));
+ break;
+ case T_DropdbStmt:
+ deparseDropdbStmt(str, castNode(DropdbStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(str, castNode(ExecuteStmt, node));
+ break;
+ case T_ExplainStmt:
+ deparseExplainStmt(str, castNode(ExplainStmt, node));
+ break;
+ case T_FetchStmt:
+ deparseFetchStmt(str, castNode(FetchStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(str, castNode(GrantStmt, node));
+ break;
+ case T_GrantRoleStmt:
+ deparseGrantRoleStmt(str, castNode(GrantRoleStmt, node));
+ break;
+ case T_ImportForeignSchemaStmt:
+ deparseImportForeignSchemaStmt(str, castNode(ImportForeignSchemaStmt, node));
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(str, castNode(IndexStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(str, castNode(InsertStmt, node));
+ break;
+ case T_ListenStmt:
+ deparseListenStmt(str, castNode(ListenStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_LoadStmt:
+ deparseLoadStmt(str, castNode(LoadStmt, node));
+ break;
+ case T_LockStmt:
+ deparseLockStmt(str, castNode(LockStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(str, castNode(MergeStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(str, castNode(NotifyStmt, node));
+ break;
+ case T_PrepareStmt:
+ deparsePrepareStmt(str, castNode(PrepareStmt, node));
+ break;
+ case T_ReassignOwnedStmt:
+ deparseReassignOwnedStmt(str, castNode(ReassignOwnedStmt, node));
+ break;
+ case T_ReindexStmt:
+ deparseReindexStmt(str, castNode(ReindexStmt, node));
+ break;
+ case T_RenameStmt:
+ deparseRenameStmt(str, castNode(RenameStmt, node));
+ break;
+ case T_RuleStmt:
+ deparseRuleStmt(str, castNode(RuleStmt, node));
+ break;
+ case T_SecLabelStmt:
+ deparseSecLabelStmt(str, castNode(SecLabelStmt, node));
+ break;
+ case T_SelectStmt:
+ deparseSelectStmt(str, castNode(SelectStmt, node));
+ break;
+ case T_TransactionStmt:
+ deparseTransactionStmt(str, castNode(TransactionStmt, node));
+ break;
+ case T_TruncateStmt:
+ deparseTruncateStmt(str, castNode(TruncateStmt, node));
+ break;
+ case T_UnlistenStmt:
+ deparseUnlistenStmt(str, castNode(UnlistenStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(str, castNode(UpdateStmt, node));
+ break;
+ case T_VacuumStmt:
+ deparseVacuumStmt(str, castNode(VacuumStmt, node));
+ break;
+ case T_VariableSetStmt:
+ deparseVariableSetStmt(str, castNode(VariableSetStmt, node));
+ break;
+ case T_VariableShowStmt:
+ deparseVariableShowStmt(str, castNode(VariableShowStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(str, castNode(ViewStmt, node));
+ break;
+ // These node types are created by DefineStmt grammar for CREATE TYPE in some cases
+ case T_CompositeTypeStmt:
+ deparseCompositeTypeStmt(str, castNode(CompositeTypeStmt, node));
+ break;
+ case T_CreateEnumStmt:
+ deparseCreateEnumStmt(str, castNode(CreateEnumStmt, node));
+ break;
+ case T_CreateRangeStmt:
+ deparseCreateRangeStmt(str, castNode(CreateRangeStmt, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
+ }
+}
+#endif
diff --git a/postgres_deparse.17.c b/postgres_deparse.17.c
new file mode 100644
index 0000000..634bbf1
--- /dev/null
+++ b/postgres_deparse.17.c
@@ -0,0 +1,12143 @@
+#include "pg_config.h"
+#if(PG_MAJORVERSION_NUM == 17)
+
+// From https://github.com/pganalyze/libpg_query/blob/17-6.2.2/src/postgres_deparse.c
+
+// Copyright (c) 2015, Lukas Fittl
+// Copyright (c) 2016-2023, Duboce Labs, Inc. (pganalyze)
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "postgres_deparse.h"
+
+#include "postgres.h"
+#include "catalog/index.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_trigger.h"
+#include "commands/trigger.h"
+#include "common/keywords.h"
+#include "common/kwlookup.h"
+#include "lib/stringinfo.h"
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "utils/builtins.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/xml.h"
+
+/*
+ * # Deparser overview
+ *
+ * The deparser works by walking the input parse tree and emitting into the
+ * currently active "part" as pointed to (indirectly) by the state struct.
+ *
+ * A lot of the structure of the deparser described below is meant to support
+ * the optional "pretty print" mode that can be enabled and configured through
+ * the deparser options, and inserts whitespace (newlines/spaces) as needed to
+ * make the output easier to read.
+ *
+ * ## Nesting levels
+ *
+ * Starting at the state struct we have a currently active "nesting level",
+ * which indicates the base indentation, as well as contains one or more part
+ * groups, each of which has one or more parts.
+ *
+ * Nesting levels are typically opened, or "increased", when processing a new
+ * statement contained within other statements, or for certain statement-like
+ * constructs (e.g. CASE clauses) that require custom indendation.
+ *
+ * Nesting levels are closed, or "decreased", when exiting such statements or
+ * statement-like constructs. During this operation all parts and subparts get
+ * flattened (turned into a simple list of parts), and are added to the parent
+ * nesting level.
+ *
+ * At the end of the tree walk the parts of the top most nesting level get
+ * emitted into the output string, formatted based on the deparse options.
+ *
+ * ## Part groups
+ *
+ * Part groups are usually started for each "major" keyword, which is chosen
+ * for how the output is intended to be laid out. For example, the "FROM"
+ * keyword in a SELECT statement is considered "major" and starts a new part
+ * group, vs the "JOIN" keyword is not, and as such both regular tables and
+ * JOIN clauses will be within one part group.
+ *
+ * ## Parts, indentation and merging
+ *
+ * The parts contained in part groups may be indented one additional level
+ * beyond the base indentation of the currently active nesting level, to help
+ * differentiate them from the major keywords. This can be turned off with
+ * DEPARSE_PART_NO_INDENT, for example as needed to format WITH clauses
+ * effectively.
+ *
+ * Parts may be merged with other parts within the same group, if the indent
+ * mode is set to DEPARSE_PART_INDENT_AND_MERGE. This is utilized to put
+ * certain items, for example the target list items in SELECT on one or more
+ * lines, breaking at separators as needed to respect the maximum line limit.
+ *
+ * ## Node context
+ *
+ * Node context is used when the same function in the deparser needs to behave
+ * differently depending on the parent node. For example, a SELECT statement
+ * needs wrapping parenthesis in certain situations where the parent statement
+ * uses a set operation (e.g. UNION).
+ *
+ * ## Comments
+ *
+ * Comments do not exist as nodes in a Postgres parse tree, and as such need to
+ * be passed in separately through the deparser options. They are placed in the
+ * output on a best effort basis, by matching against node locations. Comments
+ * will only be output at most once, but may not be output at all in certain
+ * cases, for example when the comment's specified match location is never
+ * reached by any of the nodes visited.
+ */
+
+typedef enum DeparseNodeContext {
+ DEPARSE_NODE_CONTEXT_NONE,
+ // Parent node type (and sometimes field)
+ DEPARSE_NODE_CONTEXT_INSERT_RELATION,
+ DEPARSE_NODE_CONTEXT_INSERT_SELECT,
+ DEPARSE_NODE_CONTEXT_A_EXPR,
+ DEPARSE_NODE_CONTEXT_CREATE_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_TYPE,
+ DEPARSE_NODE_CONTEXT_SET_STATEMENT,
+ DEPARSE_NODE_CONTEXT_FUNC_EXPR,
+ DEPARSE_NODE_CONTEXT_SELECT_SETOP,
+ DEPARSE_NODE_CONTEXT_SELECT_SORT_CLAUSE,
+ // Identifier vs constant context
+ DEPARSE_NODE_CONTEXT_IDENTIFIER,
+ DEPARSE_NODE_CONTEXT_CONSTANT
+} DeparseNodeContext;
+
+typedef enum DeparsePartIndentMode {
+ /* Don't indent parts at all, used in special cases (e.g. WITH clauses) */
+ DEPARSE_PART_NO_INDENT,
+
+ /* Indent parts but don't merge them (keep each on their own line) */
+ DEPARSE_PART_INDENT,
+
+ /* Indent parts and merge them together up to the max line length */
+ DEPARSE_PART_INDENT_AND_MERGE
+} DeparsePartIndentMode;
+
+// Each part is typically one line to be emitted in pretty print mode
+typedef struct DeparseStatePart
+{
+ StringInfo str;
+
+ /* If this gets emitted as its own line, number of spaces to be added as indentation */
+ int indent;
+
+ /* Allow merging this part with adjacent parts that are marked as mergeable */
+ bool mergeable;
+} DeparseStatePart;
+
+// A part group are typically all parts associated with a major keyword
+typedef struct DeparseStatePartGroup
+{
+ const char *keyword;
+ List *parts;
+ DeparsePartIndentMode indent_mode;
+} DeparseStatePartGroup;
+
+// Nesting levels may be statements, or complex parts of statements that should be indented (e.g. CASE)
+typedef struct DeparseStateNestingLevel
+{
+ /* List of DeparseStatePartGroup items */
+ List *part_groups;
+
+ /* Add this much indentation to every part */
+ int base_indent;
+} DeparseStateNestingLevel;
+
+typedef struct DeparseState
+{
+ DeparseStateNestingLevel *current;
+
+ /* List of DeparseStatePart items */
+ List *result_parts;
+
+ /* Deparse options originally passed in */
+ PostgresDeparseOpts opts;
+
+ /* Set of indexes of comments already placed in the output query */
+ Bitmapset *emitted_comments;
+} DeparseState;
+
+static void deparseSelectStmt(DeparseState *state, SelectStmt *stmt, DeparseNodeContext context);
+static void deparseIntoClause(DeparseState *state, IntoClause *into_clause);
+static void deparseRangeVar(DeparseState *state, RangeVar *range_var, DeparseNodeContext context);
+static void deparseResTarget(DeparseState *state, ResTarget *res_target, DeparseNodeContext context);
+static void deparseAlias(DeparseState *state, Alias *alias);
+static void deparseWindowDef(DeparseState *state, WindowDef* window_def);
+static void deparseColumnRef(DeparseState *state, ColumnRef* column_ref);
+static void deparseSubLink(DeparseState *state, SubLink* sub_link);
+static void deparseAExpr(DeparseState *state, A_Expr* a_expr, DeparseNodeContext context);
+static void deparseBoolExpr(DeparseState *state, BoolExpr *bool_expr);
+static void deparseAStar(DeparseState *state, A_Star* a_star);
+static void deparseCollateClause(DeparseState *state, CollateClause* collate_clause);
+static void deparseSortBy(DeparseState *state, SortBy* sort_by);
+static void deparseParamRef(DeparseState *state, ParamRef* param_ref);
+static void deparseSQLValueFunction(DeparseState *state, SQLValueFunction* sql_value_function);
+static void deparseWithClause(DeparseState *state, WithClause *with_clause);
+static void deparseJoinExpr(DeparseState *state, JoinExpr *join_expr);
+static void deparseCommonTableExpr(DeparseState *state, CommonTableExpr *cte);
+static void deparseRangeSubselect(DeparseState *state, RangeSubselect *range_subselect);
+static void deparseRangeFunction(DeparseState *state, RangeFunction *range_func);
+static void deparseAArrayExpr(DeparseState *state, A_ArrayExpr * array_expr);
+static void deparseRowExpr(DeparseState *state, RowExpr *row_expr);
+static void deparseTypeCast(DeparseState *state, TypeCast *type_cast, DeparseNodeContext context);
+static void deparseTypeName(DeparseState *state, TypeName *type_name);
+static void deparseIntervalTypmods(DeparseState *state, TypeName *type_name);
+static void deparseNullTest(DeparseState *state, NullTest *null_test);
+static void deparseCaseExpr(DeparseState *state, CaseExpr *case_expr);
+static void deparseCaseWhen(DeparseState *state, CaseWhen *case_when);
+static void deparseAIndirection(DeparseState *state, A_Indirection *a_indirection);
+static void deparseAIndices(DeparseState *state, A_Indices *a_indices);
+static void deparseCoalesceExpr(DeparseState *state, CoalesceExpr *coalesce_expr);
+static void deparseBooleanTest(DeparseState *state, BooleanTest *boolean_test);
+static void deparseColumnDef(DeparseState *state, ColumnDef *column_def);
+static void deparseInsertStmt(DeparseState *state, InsertStmt *insert_stmt);
+static void deparseOnConflictClause(DeparseState *state, OnConflictClause *on_conflict_clause);
+static void deparseIndexElem(DeparseState *state, IndexElem* index_elem);
+static void deparseUpdateStmt(DeparseState *state, UpdateStmt *update_stmt);
+static void deparseDeleteStmt(DeparseState *state, DeleteStmt *delete_stmt);
+static void deparseLockingClause(DeparseState *state, LockingClause *locking_clause);
+static void deparseSetToDefault(DeparseState *state, SetToDefault *set_to_default);
+static void deparseCreateCastStmt(DeparseState *state, CreateCastStmt *create_cast_stmt);
+static void deparseCreateDomainStmt(DeparseState *state, CreateDomainStmt *create_domain_stmt);
+static void deparseFunctionParameter(DeparseState *state, FunctionParameter *function_parameter);
+static void deparseRoleSpec(DeparseState *state, RoleSpec *role_spec);
+static void deparseViewStmt(DeparseState *state, ViewStmt *view_stmt);
+static void deparseVariableSetStmt(DeparseState *state, VariableSetStmt* variable_set_stmt);
+static void deparseReplicaIdentityStmt(DeparseState *state, ReplicaIdentityStmt *replica_identity_stmt);
+static void deparseRangeTableSample(DeparseState *state, RangeTableSample *range_table_sample);
+static void deparseRangeTableFunc(DeparseState *state, RangeTableFunc* range_table_func);
+static void deparseGroupingSet(DeparseState *state, GroupingSet *grouping_set);
+static void deparseFuncCall(DeparseState *state, FuncCall *func_call, DeparseNodeContext context);
+static void deparseMinMaxExpr(DeparseState *state, MinMaxExpr *min_max_expr);
+static void deparseXmlExpr(DeparseState *state, XmlExpr* xml_expr, DeparseNodeContext context);
+static void deparseXmlSerialize(DeparseState *state, XmlSerialize *xml_serialize);
+static void deparseJsonIsPredicate(DeparseState *state, JsonIsPredicate *json_is_predicate);
+static void deparseJsonObjectAgg(DeparseState *state, JsonObjectAgg *json_object_agg);
+static void deparseJsonArrayAgg(DeparseState *state, JsonArrayAgg *json_array_agg);
+static void deparseJsonObjectConstructor(DeparseState *state, JsonObjectConstructor *json_object_constructor);
+static void deparseJsonArrayConstructor(DeparseState *state, JsonArrayConstructor *json_array_constructor);
+static void deparseJsonArrayQueryConstructor(DeparseState *state, JsonArrayQueryConstructor *json_array_query_constructor);
+static void deparseJsonValueExpr(DeparseState *state, JsonValueExpr *json_value_expr);
+static void deparseJsonOutput(DeparseState *state, JsonOutput *json_output);
+static void deparseJsonParseExpr(DeparseState *state, JsonParseExpr *json_parse_expr);
+static void deparseJsonScalarExpr(DeparseState *state, JsonScalarExpr *json_scalar_expr);
+static void deparseJsonSerializeExpr(DeparseState *state, JsonSerializeExpr *json_serialize_expr);
+static void deparseJsonTable(DeparseState *state, JsonTable *json_table);
+static void deparseJsonTableColumn(DeparseState *state, JsonTableColumn *json_table_column);
+static void deparseJsonTableColumns(DeparseState *state, List *json_table_columns);
+static void deparseJsonTablePathSpec(DeparseState *state, JsonTablePathSpec *json_table_path_spec);
+static void deparseJsonBehavior(DeparseState *state, JsonBehavior *json_behavior);
+static void deparseJsonFuncExpr(DeparseState *state, JsonFuncExpr *json_func_expr);
+static void deparseJsonQuotesClauseOpt(DeparseState *state, JsonQuotes quotes);
+static void deparseJsonOnErrorClauseOpt(DeparseState *state, JsonBehavior *behavior);
+static void deparseJsonOnEmptyClauseOpt(DeparseState *state, JsonBehavior *behavior);
+static void deparseConstraint(DeparseState *state, Constraint *constraint);
+static void deparseSchemaStmt(DeparseState *state, Node *node);
+static void deparseExecuteStmt(DeparseState *state, ExecuteStmt *execute_stmt);
+static void deparseTriggerTransition(DeparseState *state, TriggerTransition *trigger_transition);
+static void deparseCreateOpClassItem(DeparseState *state, CreateOpClassItem *create_op_class_item);
+static void deparseAConst(DeparseState *state, A_Const *a_const);
+static void deparseGroupingFunc(DeparseState *state, GroupingFunc *grouping_func);
+
+static void deparsePreparableStmt(DeparseState *state, Node *node);
+static void deparseRuleActionStmt(DeparseState *state, Node *node);
+static void deparseExplainableStmt(DeparseState *state, Node *node);
+static void deparseStmt(DeparseState *state, Node *node);
+static void deparseValue(DeparseState *state, union ValUnion *value, DeparseNodeContext context);
+
+static void
+removeTrailingSpaceFromStr(StringInfo str)
+{
+ if (str->len >= 1 && str->data[str->len - 1] == ' ') {
+ str->len -= 1;
+ str->data[str->len] = '\0';
+ }
+}
+
+// Check whether the value is a reserved keyword, to determine escaping for output
+//
+// Note that since the parser lowercases all keywords, this does *not* match when the
+// value is not all-lowercase and a reserved keyword.
+static bool
+isReservedKeyword(const char *val)
+{
+ int kwnum = ScanKeywordLookup(val, &ScanKeywords);
+ bool all_lower_case = true;
+ const char *cp;
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ (*cp >= 'a' && *cp <= 'z') ||
+ (*cp >= '0' && *cp <= '9') ||
+ (*cp == '_')))
+ {
+ all_lower_case = false;
+ break;
+ }
+ }
+
+ return all_lower_case && kwnum >= 0 && ScanKeywordCategories[kwnum] == RESERVED_KEYWORD;
+}
+
+// Returns whether the given value consists only of operator characters
+static bool
+isOp(const char *val)
+{
+ const char *cp;
+
+ Assert(strlen(val) > 0);
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ *cp == '~' ||
+ *cp == '!' ||
+ *cp == '@' ||
+ *cp == '#' ||
+ *cp == '^' ||
+ *cp == '&' ||
+ *cp == '|' ||
+ *cp == '`' ||
+ *cp == '?' ||
+ *cp == '+' ||
+ *cp == '-' ||
+ *cp == '*' ||
+ *cp == '/' ||
+ *cp == '%' ||
+ *cp == '<' ||
+ *cp == '>' ||
+ *cp == '='))
+ return false;
+ }
+
+ return true;
+}
+
+static DeparseStatePart *
+makeDeparseStatePart(DeparseState *state, DeparseStateNestingLevel *level, DeparsePartIndentMode indent_mode)
+{
+ DeparseStatePart *part = palloc(sizeof(DeparseStatePart));
+ part->str = makeStringInfo();
+ part->indent = level->base_indent;
+ if (indent_mode != DEPARSE_PART_NO_INDENT)
+ part->indent += state->opts.indent_size;
+ part->mergeable = indent_mode == DEPARSE_PART_INDENT_AND_MERGE;
+ return part;
+}
+
+static void
+freeDeparseStatePart(DeparseStatePart *part)
+{
+ pfree(part->str->data);
+ pfree(part->str);
+ pfree(part);
+}
+
+// Returns current active part group, and initializes the first one (including an empty part) if needed
+static DeparseStatePartGroup *
+deparseGetCurrentPartGroup(DeparseState *state)
+{
+ DeparseStateNestingLevel *level = state->current;
+ if (level->part_groups)
+ return (DeparseStatePartGroup *) llast(level->part_groups);
+
+ DeparseStatePartGroup *part_group = palloc0(sizeof(DeparseStatePartGroup));
+ part_group->parts = lappend(part_group->parts, makeDeparseStatePart(state, level, part_group->indent_mode));
+ level->part_groups = lappend(level->part_groups, part_group);
+ return part_group;
+}
+
+static DeparseStatePart *
+deparseGetCurrentPart(DeparseState *state)
+{
+ DeparseStatePartGroup *part_group = deparseGetCurrentPartGroup(state);
+ return (DeparseStatePart *) llast(part_group->parts);
+}
+
+static void
+deparseMarkCurrentPartNonMergable(DeparseState *state)
+{
+ DeparseStatePart *part = deparseGetCurrentPart(state);
+ part->mergeable = false;
+}
+
+static StringInfo deparseGetCurrentStringInfo(DeparseState *state)
+{
+ DeparseStatePart *part = deparseGetCurrentPart(state);
+ Assert(part != NULL);
+ return part->str;
+}
+
+static void deparseAppendStringInfo(DeparseState *state, const char *fmt,...)
+{
+ StringInfo str = deparseGetCurrentStringInfo(state);
+ int save_errno = errno;
+
+ for (;;)
+ {
+ va_list args;
+ int needed;
+
+ /* Try to format the data. */
+ errno = save_errno;
+ va_start(args, fmt);
+ needed = appendStringInfoVA(str, fmt, args);
+ va_end(args);
+
+ if (needed == 0)
+ break; /* success */
+
+ /* Increase the buffer size and try again. */
+ enlargeStringInfo(str, needed);
+ }
+}
+
+static void deparseAppendStringInfoString(DeparseState *state, const char *s)
+{
+ StringInfo str = deparseGetCurrentStringInfo(state);
+ appendStringInfoString(str, s);
+}
+
+static void deparseAppendStringInfoChar(DeparseState *state, char ch)
+{
+ StringInfo str = deparseGetCurrentStringInfo(state);
+ appendStringInfoChar(str, ch);
+}
+
+static void
+removeTrailingSpace(DeparseState *state)
+{
+ StringInfo str = deparseGetCurrentStringInfo(state);
+ removeTrailingSpaceFromStr(str);
+}
+
+static void
+deparseRemoveTrailingEmptyPart(DeparseState *state)
+{
+ DeparseStatePartGroup *part_group = deparseGetCurrentPartGroup(state);
+ DeparseStatePart *last_part = deparseGetCurrentPart(state);
+
+ if (last_part->str->len == 0)
+ {
+ freeDeparseStatePart(last_part);
+ part_group->parts = list_delete_last(part_group->parts);
+ }
+}
+
+static void
+deparseAppendPart(DeparseState *state, bool deduplicate)
+{
+ DeparseStatePartGroup *part_group = deparseGetCurrentPartGroup(state);
+
+ // Remove previous part if its empty and we deduplicate. We don't keep
+ // the existing part since it may have the wrong indent level or mode.
+ if (deduplicate)
+ deparseRemoveTrailingEmptyPart(state);
+
+ part_group->parts = lappend(part_group->parts, makeDeparseStatePart(state, state->current, part_group->indent_mode));
+}
+
+static void
+deparseAppendCommaAndPart(DeparseState *state)
+{
+ if (state->opts.commas_start_of_line)
+ {
+ deparseAppendPart(state, true);
+ deparseAppendStringInfoString(state, ", ");
+ }
+ else
+ {
+ deparseAppendStringInfoChar(state, ',');
+ deparseAppendPart(state, true);
+ }
+}
+
+static void
+deparseAppendPartGroup(DeparseState *state, const char *keyword, DeparsePartIndentMode indent_mode)
+{
+ DeparseStateNestingLevel *level = state->current;
+ DeparseStatePartGroup *part_group = palloc0(sizeof(DeparseStatePartGroup));
+
+ if (list_length(level->part_groups) > 0)
+ removeTrailingSpace(state);
+
+ part_group->keyword = keyword;
+ part_group->parts = lappend(part_group->parts, makeDeparseStatePart(state, state->current, indent_mode));
+ part_group->indent_mode = indent_mode;
+
+ level->part_groups = lappend(level->part_groups, part_group);
+}
+
+static void
+deparseAppendCommentsIfNeeded(DeparseState *state, ParseLoc location)
+{
+ for (int i = 0; i < state->opts.comment_count; i++)
+ {
+ if (bms_is_member(i, state->emitted_comments))
+ continue;
+
+ PostgresDeparseComment *comment = state->opts.comments[i];
+ if (comment->match_location > location)
+ continue;
+
+ // Emit one less leading newline if we already emitted one for formatting reasons
+ int newlines_before_comment = comment->newlines_before_comment;
+ if (state->opts.pretty_print && newlines_before_comment > 0 &&
+ deparseGetCurrentPartGroup(state)->keyword != NULL &&
+ deparseGetCurrentStringInfo(state)->len == 0)
+ newlines_before_comment -= 1;
+
+ for (int j = 0; j < newlines_before_comment; j++)
+ {
+ if (state->opts.pretty_print)
+ deparseAppendPart(state, false);
+ else
+ deparseAppendStringInfoChar(state, '\n');
+ }
+
+ deparseAppendStringInfoString(state, comment->str);
+
+ /* never merge comments with other parts */
+ deparseMarkCurrentPartNonMergable(state);
+
+ for (int j = 0; j < comment->newlines_after_comment; j++)
+ {
+ if (state->opts.pretty_print)
+ deparseAppendPart(state, false);
+ else
+ deparseAppendStringInfoChar(state, '\n');
+ }
+
+ state->emitted_comments = bms_add_member(state->emitted_comments, i);
+ }
+}
+
+static void
+deparseEmit(DeparseState *state, StringInfo str)
+{
+ ListCell *lc;
+
+ /* If the last part is empty, drop it, so we don't confuse the newline output */
+ DeparseStatePart *last_part = (DeparseStatePart *) llast(state->result_parts);
+ if (last_part && last_part->str->len == 0)
+ {
+ freeDeparseStatePart(last_part);
+ state->result_parts = list_delete_last(state->result_parts);
+ }
+
+ foreach (lc, state->result_parts)
+ {
+ DeparseStatePart *part = (DeparseStatePart *) lfirst(lc);
+ bool last_part = list_cell_number(state->result_parts, lc) == list_length(state->result_parts) - 1;
+
+ if (!state->opts.pretty_print && part->str->len > 0 && (part->str->data[0] == ')' || part->str->data[0] == ';'))
+ removeTrailingSpaceFromStr(str);
+
+ if (state->opts.pretty_print)
+ {
+ for (int i = 0; i < part->indent; i++)
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, part->str->data);
+ removeTrailingSpaceFromStr(str);
+
+ if (!last_part)
+ {
+ if (state->opts.pretty_print)
+ appendStringInfoChar(str, '\n');
+ else if (str->data[str->len - 1] != '(')
+ appendStringInfoChar(str, ' ');
+ }
+
+ freeDeparseStatePart(part);
+ }
+ list_free(state->result_parts);
+ state->result_parts = NIL;
+
+ if (state->opts.pretty_print && state->opts.trailing_newline)
+ appendStringInfoChar(str, '\n');
+}
+
+static DeparseStateNestingLevel *
+deparseStateIncreaseNestingLevel(DeparseState *state)
+{
+ DeparseStateNestingLevel *parent = state->current;
+ DeparseStateNestingLevel *level = palloc0(sizeof(DeparseStateNestingLevel));
+ if (parent)
+ {
+ DeparseStatePartGroup *part_group = deparseGetCurrentPartGroup(state);
+ level->base_indent = parent->base_indent + state->opts.indent_size;
+ if (part_group->indent_mode != DEPARSE_PART_NO_INDENT) /* Indent again if parts next to us are also indented */
+ level->base_indent += state->opts.indent_size;
+
+ /* Parts with nested elements don't get merged, even if otherwise permitted */
+ deparseMarkCurrentPartNonMergable(state);
+ }
+ state->current = level;
+ return parent;
+}
+
+static void
+deparseStateDecreaseNestingLevel(DeparseState *state, DeparseStateNestingLevel *parent_level)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ DeparseStateNestingLevel *level = state->current;
+ Assert(level != NULL);
+
+ foreach (lc, level->part_groups)
+ {
+ DeparseStatePartGroup *part_group = (DeparseStatePartGroup *) lfirst(lc);
+
+ /* Merge parts */
+ if (part_group->indent_mode == DEPARSE_PART_INDENT_AND_MERGE && list_length(part_group->parts) > 1)
+ {
+ DeparseStatePart *target = (DeparseStatePart *) linitial(part_group->parts);
+ for_each_from (lc2, part_group->parts, 1)
+ {
+ DeparseStatePart *part = (DeparseStatePart *) lfirst(lc2);
+ removeTrailingSpaceFromStr(target->str);
+ if (target->mergeable && part->mergeable &&
+ target->indent + target->str->len + 1 + part->str->len <= state->opts.max_line_length)
+ {
+ if (target->str->len > 0 && target->str->data[target->str->len - 1] != '(')
+ appendStringInfoChar(target->str, ' ');
+ appendStringInfoString(target->str, part->str->data);
+ freeDeparseStatePart(part);
+ part_group->parts = foreach_delete_current(part_group->parts, lc2);
+ }
+ else
+ {
+ target = part;
+ }
+ }
+ }
+
+ if (part_group->keyword != NULL)
+ {
+ DeparseStatePart *target = makeDeparseStatePart(state, level, false);
+ appendStringInfoString(target->str, part_group->keyword);
+ part_group->parts = list_insert_nth(part_group->parts, 0, target);
+
+ if (list_length(part_group->parts) == 2 || part_group->indent_mode == DEPARSE_PART_NO_INDENT)
+ {
+ DeparseStatePart *part = (DeparseStatePart *) lsecond(part_group->parts);
+ if (part->str->len > 0)
+ appendStringInfo(target->str, " %s", part->str->data);
+ freeDeparseStatePart(part);
+ part_group->parts = list_delete_nth_cell(part_group->parts, 1);
+ }
+ }
+
+ if (parent_level)
+ {
+ DeparseStatePartGroup *parent_part_group = (DeparseStatePartGroup *) llast(parent_level->part_groups);
+ parent_part_group->parts = list_concat(parent_part_group->parts, part_group->parts);
+ }
+ else
+ {
+ // If its the top level, save as results instead
+ state->result_parts = list_concat(state->result_parts, part_group->parts);
+ }
+
+ list_free(part_group->parts);
+ pfree(part_group);
+ }
+ list_free(level->part_groups);
+ pfree(level);
+
+ state->current = parent_level;
+
+ if (parent_level)
+ {
+ /* Make sure parent statement writes that follow are on their own line */
+ deparseAppendPart(state, true);
+
+ /* Parts with nested elements don't get merged, even if otherwise permitted */
+ deparseMarkCurrentPartNonMergable(state);
+ }
+}
+
+/*
+ * Append a SQL string literal representing "val" to buf.
+ *
+ * Copied here from postgres_fdw/deparse.c to avoid adding
+ * many additional dependencies, and modified to work with deparser
+ * state.
+ */
+static void
+deparseStringLiteral(DeparseState *state, const char *val)
+{
+ const char *valptr;
+
+ /*
+ * Rather than making assumptions about the remote server's value of
+ * standard_conforming_strings, always use E'foo' syntax if there are any
+ * backslashes. This will fail on remote servers before 8.1, but those
+ * are long out of support.
+ */
+ if (strchr(val, '\\') != NULL)
+ deparseAppendStringInfoChar(state, ESCAPE_STRING_SYNTAX);
+ deparseAppendStringInfoChar(state, '\'');
+ for (valptr = val; *valptr; valptr++)
+ {
+ char ch = *valptr;
+
+ if (SQL_STR_DOUBLE(ch, true))
+ deparseAppendStringInfoChar(state, ch);
+ deparseAppendStringInfoChar(state, ch);
+ }
+ deparseAppendStringInfoChar(state, '\'');
+}
+
+// "any_name" in gram.y
+static void deparseAnyName(DeparseState *state, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, parts)
+ {
+ Assert(IsA(lfirst(lc), String));
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ deparseAppendStringInfoChar(state, '.');
+ }
+}
+static void deparseAnyNameSkipFirst(DeparseState *state, List *parts)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, parts, 1)
+ {
+ Assert(IsA(lfirst(lc), String));
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ deparseAppendStringInfoChar(state, '.');
+ }
+}
+static void deparseAnyNameSkipLast(DeparseState *state, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, parts)
+ {
+ if (lnext(parts, lc))
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (foreach_current_index(lc) < list_length(parts) - 2)
+ deparseAppendStringInfoChar(state, '.');
+ }
+ }
+}
+
+// "func_expr" in gram.y
+static void deparseFuncExpr(DeparseState *state, Node *node, DeparseNodeContext context)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(state, castNode(FuncCall, node), context);
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(state, castNode(SQLValueFunction, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(state, castNode(MinMaxExpr, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(state, castNode(CoalesceExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(state, castNode(XmlExpr, node), context);
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(state, castNode(XmlSerialize, node));
+ break;
+ case T_JsonObjectAgg:
+ deparseJsonObjectAgg(state, castNode(JsonObjectAgg, node));
+ break;
+ case T_JsonArrayAgg:
+ deparseJsonArrayAgg(state, castNode(JsonArrayAgg, node));
+ break;
+ case T_JsonObjectConstructor:
+ deparseJsonObjectConstructor(state, castNode(JsonObjectConstructor, node));
+ break;
+ case T_JsonArrayConstructor:
+ deparseJsonArrayConstructor(state, castNode(JsonArrayConstructor, node));
+ break;
+ case T_JsonArrayQueryConstructor:
+ deparseJsonArrayQueryConstructor(state, castNode(JsonArrayQueryConstructor, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in func_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+static void deparseCExpr(DeparseState *state, Node *node);
+
+// "a_expr" in gram.y
+static void deparseExpr(DeparseState *state, Node *node, DeparseNodeContext context)
+{
+ if (node == NULL)
+ return;
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ case T_A_Const:
+ case T_ParamRef:
+ case T_A_Indirection:
+ case T_CaseExpr:
+ case T_SubLink:
+ case T_A_ArrayExpr:
+ case T_RowExpr:
+ case T_GroupingFunc:
+ deparseCExpr(state, node);
+ break;
+ case T_TypeCast:
+ deparseTypeCast(state, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_CollateClause:
+ deparseCollateClause(state, castNode(CollateClause, node));
+ break;
+ case T_A_Expr:
+ deparseAExpr(state, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_A_EXPR);
+ break;
+ case T_BoolExpr:
+ deparseBoolExpr(state, castNode(BoolExpr, node));
+ break;
+ case T_NullTest:
+ deparseNullTest(state, castNode(NullTest, node));
+ break;
+ case T_BooleanTest:
+ deparseBooleanTest(state, castNode(BooleanTest, node));
+ break;
+ case T_JsonIsPredicate:
+ deparseJsonIsPredicate(state, castNode(JsonIsPredicate, node));
+ break;
+ case T_SetToDefault:
+ deparseSetToDefault(state, castNode(SetToDefault, node));
+ break;
+ case T_MergeSupportFunc:
+ deparseAppendStringInfoString(state, "merge_action() ");
+ break;
+ case T_JsonParseExpr:
+ deparseJsonParseExpr(state, castNode(JsonParseExpr, node));
+ break;
+ case T_JsonScalarExpr:
+ deparseJsonScalarExpr(state, castNode(JsonScalarExpr, node));
+ break;
+ case T_JsonSerializeExpr:
+ deparseJsonSerializeExpr(state, castNode(JsonSerializeExpr, node));
+ break;
+ case T_JsonFuncExpr:
+ deparseJsonFuncExpr(state, castNode(JsonFuncExpr, node));
+ break;
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_MinMaxExpr:
+ case T_CoalesceExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ case T_JsonObjectAgg:
+ case T_JsonArrayAgg:
+ case T_JsonObjectConstructor:
+ case T_JsonArrayConstructor:
+ case T_JsonArrayQueryConstructor:
+ deparseFuncExpr(state, node, context);
+ break;
+ default:
+ // Note that this is also the fallthrough for deparseBExpr and deparseCExpr
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr/c_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "b_expr" in gram.y
+static void deparseBExpr(DeparseState *state, Node *node)
+{
+ if (IsA(node, XmlExpr)) {
+ deparseXmlExpr(state, castNode(XmlExpr, node), DEPARSE_NODE_CONTEXT_NONE);
+ return;
+ }
+
+ if (IsA(node, A_Expr)) {
+ A_Expr *a_expr = castNode(A_Expr, node);
+ // Other kinds are handled by "c_expr", with parens added around them
+ if (a_expr->kind == AEXPR_OP || a_expr->kind == AEXPR_DISTINCT || a_expr->kind == AEXPR_NOT_DISTINCT) {
+ deparseAExpr(state, a_expr, DEPARSE_NODE_CONTEXT_NONE);
+ return;
+ }
+ }
+
+ if (IsA(node, BoolExpr)) {
+ BoolExpr *bool_expr = castNode(BoolExpr, node);
+ if (bool_expr->boolop == NOT_EXPR) {
+ deparseBoolExpr(state, bool_expr);
+ return;
+ }
+ }
+
+ deparseCExpr(state, node);
+}
+
+// "AexprConst" in gram.y
+static void deparseAexprConst(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_A_Const:
+ deparseAConst(state, castNode(A_Const, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(state, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in AexprConst: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "c_expr" in gram.y
+static void deparseCExpr(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ deparseColumnRef(state, castNode(ColumnRef, node));
+ break;
+ case T_A_Const:
+ deparseAConst(state, castNode(A_Const, node));
+ break;
+ case T_ParamRef:
+ deparseParamRef(state, castNode(ParamRef, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(state, castNode(A_Indirection, node));
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(state, castNode(CaseExpr, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(state, castNode(SubLink, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(state, castNode(A_ArrayExpr, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(state, castNode(RowExpr, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(state, castNode(GroupingFunc, node));
+ break;
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_MinMaxExpr:
+ case T_CoalesceExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ case T_JsonObjectAgg:
+ case T_JsonArrayAgg:
+ case T_JsonObjectConstructor:
+ case T_JsonArrayConstructor:
+ case T_JsonArrayQueryConstructor:
+ deparseFuncExpr(state, node, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ deparseAppendStringInfoChar(state, '(');
+ // Because we wrap this in parenthesis, the expression inside follows "a_expr" parser rules
+ deparseExpr(state, node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ }
+}
+
+// "expr_list" in gram.y
+static void deparseExprList(DeparseState *state, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseExpr(state, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (lnext(exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
+static void deparseColId(DeparseState *state, char *s)
+{
+ deparseAppendStringInfoString(state, quote_identifier(s));
+}
+
+// "ColLabel", "attr_name"
+//
+// Note this is kept separate from ColId in case we ever want to be more
+// specific on how to handle keywords here
+static void deparseColLabel(DeparseState *state, char *s)
+{
+ deparseAppendStringInfoString(state, quote_identifier(s));
+}
+
+// "SignedIconst" and "Iconst" in gram.y
+static void deparseSignedIconst(DeparseState *state, Node *node)
+{
+ deparseAppendStringInfo(state, "%d", intVal(node));
+}
+
+// "indirection" and "opt_indirection" in gram.y
+static void deparseOptIndirection(DeparseState *state, List *indirection, int N)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, indirection, N)
+ {
+ if (IsA(lfirst(lc), String))
+ {
+ deparseAppendStringInfoChar(state, '.');
+ deparseColLabel(state, strVal(lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Star))
+ {
+ deparseAppendStringInfoString(state, ".*");
+ }
+ else if (IsA(lfirst(lc), A_Indices))
+ {
+ deparseAIndices(state, castNode(A_Indices, lfirst(lc)));
+ }
+ else
+ {
+ // No other nodes should appear here
+ Assert(false);
+ }
+ }
+}
+
+// "role_list" in gram.y
+static void deparseRoleList(DeparseState *state, List *roles)
+{
+ ListCell *lc;
+
+ foreach(lc, roles)
+ {
+ RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
+ deparseRoleSpec(state, role_spec);
+ if (lnext(roles, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "SimpleTypename" in gram.y
+static void deparseSimpleTypename(DeparseState *state, Node *node)
+{
+ deparseTypeName(state, castNode(TypeName, node));
+}
+
+// "NumericOnly" in gram.y
+static void deparseNumericOnly(DeparseState *state, union ValUnion *value)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ deparseAppendStringInfo(state, "%d", value->ival.ival);
+ break;
+ case T_Float:
+ deparseAppendStringInfoString(state, value->sval.sval);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "NumericOnly_list" in gram.y
+static void deparseNumericOnlyList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseNumericOnly(state, (union ValUnion *) lfirst(lc));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "SeqOptElem" in gram.y
+static void deparseSeqOptElem(DeparseState *state, DefElem *def_elem)
+{
+ ListCell *lc;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ deparseAppendStringInfoString(state, "AS ");
+ deparseSimpleTypename(state, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cache") == 0)
+ {
+ deparseAppendStringInfoString(state, "CACHE ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NO CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "increment") == 0)
+ {
+ deparseAppendStringInfoString(state, "INCREMENT ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "MAXVALUE ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NO MAXVALUE");
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "MINVALUE ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NO MINVALUE");
+ }
+ else if (strcmp(def_elem->defname, "owned_by") == 0)
+ {
+ deparseAppendStringInfoString(state, "OWNED BY ");
+ deparseAnyName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "sequence_name") == 0)
+ {
+ deparseAppendStringInfoString(state, "SEQUENCE NAME ");
+ deparseAnyName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "start") == 0)
+ {
+ deparseAppendStringInfoString(state, "START ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "RESTART ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "SeqOptList" in gram.y
+static void deparseSeqOptList(DeparseState *state, List *options)
+{
+ ListCell *lc;
+ Assert(list_length(options) > 0);
+ foreach (lc, options)
+ {
+ deparseSeqOptElem(state, castNode(DefElem, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "OptSeqOptList" in gram.y
+static void deparseOptSeqOptList(DeparseState *state, List *options)
+{
+ if (list_length(options) > 0)
+ deparseSeqOptList(state, options);
+}
+
+// "OptParenthesizedSeqOptList" in gram.y
+static void deparseOptParenthesizedSeqOptList(DeparseState *state, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseSeqOptList(state, options);
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+// "opt_drop_behavior" in gram.y
+static void deparseOptDropBehavior(DeparseState *state, DropBehavior behavior)
+{
+ switch (behavior)
+ {
+ case DROP_RESTRICT:
+ // Default
+ break;
+ case DROP_CASCADE:
+ deparseAppendStringInfoString(state, "CASCADE ");
+ break;
+ }
+}
+
+// "any_operator" in gram.y
+static void deparseAnyOperator(DeparseState *state, List *op)
+{
+ Assert(isOp(strVal(llast(op))));
+ if (list_length(op) == 2)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(op))));
+ deparseAppendStringInfoChar(state, '.');
+ deparseAppendStringInfoString(state, strVal(llast(op)));
+ }
+ else if (list_length(op) == 1)
+ {
+ deparseAppendStringInfoString(state, strVal(llast(op)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "qual_Op" and "qual_all_Op" in gram.y
+static void deparseQualOp(DeparseState *state, List *op)
+{
+ if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ deparseAppendStringInfoString(state, strVal(linitial(op)));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "OPERATOR(");
+ deparseAnyOperator(state, op);
+ deparseAppendStringInfoString(state, ")");
+ }
+}
+
+// "subquery_Op" in gram.y
+static void deparseSubqueryOp(DeparseState *state, List *op)
+{
+ if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
+ {
+ deparseAppendStringInfoString(state, "LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
+ {
+ deparseAppendStringInfoString(state, "NOT LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
+ {
+ deparseAppendStringInfoString(state, "ILIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
+ {
+ deparseAppendStringInfoString(state, "NOT ILIKE");
+ }
+ else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ deparseAppendStringInfoString(state, strVal(linitial(op)));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "OPERATOR(");
+ deparseAnyOperator(state, op);
+ deparseAppendStringInfoString(state, ")");
+ }
+}
+
+// Not present directly in gram.y (usually matched by ColLabel)
+static void deparseGenericDefElemName(DeparseState *state, const char *in)
+{
+ Assert(in != NULL);
+ char *val = pstrdup(in);
+ for (unsigned char *p = (unsigned char *) val; *p; p++)
+ *p = pg_toupper(*p);
+ deparseAppendStringInfoString(state, val);
+ pfree(val);
+}
+
+// "def_arg" and "operator_def_arg" in gram.y
+static void deparseDefArg(DeparseState *state, Node *arg, bool is_operator_def_arg)
+{
+ if (IsA(arg, TypeName)) // func_type
+ {
+ deparseTypeName(state, castNode(TypeName, arg));
+ }
+ else if (IsA(arg, List)) // qual_all_Op
+ {
+ List *l = castNode(List, arg);
+ Assert(list_length(l) == 1 || list_length(l) == 2);
+
+ // Schema qualified operator
+ if (list_length(l) == 2)
+ {
+ deparseAppendStringInfoString(state, "OPERATOR(");
+ deparseAnyOperator(state, l);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ else if (list_length(l) == 1)
+ {
+ deparseAppendStringInfoString(state, strVal(linitial(l)));
+ }
+ }
+ else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
+ {
+ deparseValue(state, (union ValUnion *) arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (IsA(arg, String))
+ {
+ char *s = strVal(arg);
+ if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) // NONE
+ {
+ deparseAppendStringInfoString(state, "NONE");
+ }
+ else if (isReservedKeyword(s)) // reserved_keyword
+ {
+ deparseAppendStringInfoString(state, s);
+ }
+ else // Sconst
+ {
+ deparseStringLiteral(state, s);
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "definition" in gram.y
+static void deparseDefinition(DeparseState *state, List *options)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoChar(state, '(');
+ foreach (lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL) {
+ deparseAppendStringInfoString(state, " = ");
+ deparseDefArg(state, def_elem->arg, false);
+ }
+
+ if (lnext(options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "opt_definition" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptDefinition(DeparseState *state, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ deparseAppendStringInfoString(state, "WITH ");
+ deparseDefinition(state, options);
+ }
+}
+
+// "create_generic_options" in gram.y
+static void deparseCreateGenericOptions(DeparseState *state, List *options)
+{
+ ListCell *lc = NULL;
+
+ if (options == NULL)
+ return;
+
+ deparseAppendStringInfoString(state, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ if (lnext(options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ")");
+}
+
+// "common_func_opt_item" in gram.y
+static void deparseCommonFuncOptItem(DeparseState *state, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "strict") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "RETURNS NULL ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "strict") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "CALLED ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
+ {
+ deparseAppendStringInfoString(state, "IMMUTABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
+ {
+ deparseAppendStringInfoString(state, "STABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
+ {
+ deparseAppendStringInfoString(state, "VOLATILE");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "SECURITY DEFINER");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "SECURITY INVOKER");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOT LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "cost") == 0)
+ {
+ deparseAppendStringInfoString(state, "COST ");
+ deparseValue(state, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "rows") == 0)
+ {
+ deparseAppendStringInfoString(state, "ROWS ");
+ deparseValue(state, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "support") == 0)
+ {
+ deparseAppendStringInfoString(state, "SUPPORT ");
+ deparseAnyName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
+ {
+ deparseVariableSetStmt(state, castNode(VariableSetStmt, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "parallel") == 0)
+ {
+ deparseAppendStringInfoString(state, "PARALLEL ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(def_elem->arg)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "NonReservedWord_or_Sconst" in gram.y
+//
+// Note since both identifiers and string constants are allowed here, we
+// currently always return an identifier, except:
+//
+// 1) when the string is empty (since an empty identifier can't be scanned)
+// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
+static void deparseNonReservedWordOrSconst(DeparseState *state, const char *val)
+{
+ if (strlen(val) == 0)
+ deparseAppendStringInfoString(state, "''");
+ else if (strlen(val) >= NAMEDATALEN)
+ deparseStringLiteral(state, val);
+ else
+ deparseAppendStringInfoString(state, quote_identifier(val));
+}
+
+// "func_as" in gram.y
+static void deparseFuncAs(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ char *strval = strVal(lfirst(lc));
+ if (strstr(strval, "$$") == NULL)
+ {
+ deparseAppendStringInfoString(state, "$$");
+ deparseAppendStringInfoString(state, strval);
+ deparseAppendStringInfoString(state, "$$");
+ }
+ else
+ {
+ deparseStringLiteral(state, strval);
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "createfunc_opt_item" in gram.y
+static void deparseCreateFuncOptItem(DeparseState *state, DefElem *def_elem)
+{
+ ListCell *lc = NULL;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ deparseAppendStringInfoString(state, "AS ");
+ deparseFuncAs(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "language") == 0)
+ {
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "transform") == 0)
+ {
+ List *l = castNode(List, def_elem->arg);
+ deparseAppendStringInfoString(state, "TRANSFORM ");
+ foreach (lc, l)
+ {
+ deparseAppendStringInfoString(state, "FOR TYPE ");
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ else if (strcmp(def_elem->defname, "window") == 0)
+ {
+ deparseAppendStringInfoString(state, "WINDOW");
+ }
+ else
+ {
+ deparseCommonFuncOptItem(state, def_elem);
+ }
+}
+
+// "alter_generic_options" in gram.y
+static void deparseAlterGenericOptions(DeparseState *state, List *options)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ switch (def_elem->defaction)
+ {
+ case DEFELEM_UNSPEC:
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ break;
+ case DEFELEM_SET:
+ deparseAppendStringInfoString(state, "SET ");
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ break;
+ case DEFELEM_ADD:
+ deparseAppendStringInfoString(state, "ADD ");
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ break;
+ case DEFELEM_DROP:
+ deparseAppendStringInfoString(state, "DROP ");
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ break;
+ }
+
+ if (lnext(options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+}
+
+// "func_name" in gram.y
+static void deparseFuncName(DeparseState *state, List *func_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, func_name)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(func_name, lc))
+ deparseAppendStringInfoChar(state, '.');
+ }
+}
+
+// "function_with_argtypes" in gram.y
+static void deparseFunctionWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc;
+ deparseFuncName(state, object_with_args->objname);
+
+ if (!object_with_args->args_unspecified)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(state, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+// "function_with_argtypes_list" in gram.y
+static void deparseFunctionWithArgtypesList(DeparseState *state, List *l)
+{
+ ListCell *lc;
+
+ foreach(lc, l)
+ {
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "operator_with_argtypes" in gram.y
+static void deparseOperatorWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
+{
+ deparseAnyOperator(state, object_with_args->objname);
+
+ Assert(list_length(object_with_args->objargs) == 2);
+ deparseAppendStringInfoChar(state, '(');
+ if (linitial(object_with_args->objargs) == NULL)
+ deparseAppendStringInfoString(state, "NONE");
+ else
+ deparseTypeName(state, castNode(TypeName, linitial(object_with_args->objargs)));
+ deparseAppendStringInfoString(state, ", ");
+ if (lsecond(object_with_args->objargs) == NULL)
+ deparseAppendStringInfoString(state, "NONE");
+ else
+ deparseTypeName(state, castNode(TypeName, lsecond(object_with_args->objargs)));
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "aggr_args" in gram.y
+static void deparseAggrArgs(DeparseState *state, List *aggr_args)
+{
+ Assert(list_length(aggr_args) == 2);
+
+ ListCell *lc = NULL;
+ List *args = linitial(aggr_args);
+ int order_by_pos = intVal(lsecond(aggr_args));
+
+ deparseAppendStringInfoChar(state, '(');
+ if (args == NULL)
+ {
+ deparseAppendStringInfoChar(state, '*');
+ }
+ else
+ {
+ foreach(lc, args)
+ {
+ if (foreach_current_index(lc) == order_by_pos)
+ {
+ if (foreach_current_index(lc) > 0)
+ deparseAppendStringInfoChar(state, ' ');
+ deparseAppendStringInfoString(state, "ORDER BY ");
+ }
+ else if (foreach_current_index(lc) > 0)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseFunctionParameter(state, castNode(FunctionParameter, lfirst(lc)));
+ }
+
+ // Repeat the last direct arg as a ordered arg to handle the
+ // simplification done by makeOrderedSetArgs in gram.y
+ if (order_by_pos == list_length(args))
+ {
+ deparseAppendStringInfoString(state, " ORDER BY ");
+ deparseFunctionParameter(state, castNode(FunctionParameter, llast(args)));
+ }
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "aggregate_with_argtypes" in gram.y
+static void deparseAggregateWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc = NULL;
+
+ deparseFuncName(state, object_with_args->objname);
+
+ deparseAppendStringInfoChar(state, '(');
+ if (object_with_args->objargs == NULL && object_with_args->objfuncargs == NULL)
+ {
+ deparseAppendStringInfoChar(state, '*');
+ }
+ else
+ {
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(state, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "columnList" in gram.y
+static void deparseColumnList(DeparseState *state, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(columns, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "OptTemp" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptTemp(DeparseState *state, char relpersistence)
+{
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_PERMANENT:
+ // Default
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ deparseAppendStringInfoString(state, "UNLOGGED ");
+ break;
+ case RELPERSISTENCE_TEMP:
+ deparseAppendStringInfoString(state, "TEMPORARY ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+// "relation_expr_list" in gram.y
+static void deparseRelationExprList(DeparseState *state, List *relation_exprs)
+{
+ ListCell *lc = NULL;
+ foreach(lc, relation_exprs)
+ {
+ deparseRangeVar(state, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(relation_exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "handler_name" in gram.y
+static void deparseHandlerName(DeparseState *state, List *handler_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, handler_name)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(handler_name, lc))
+ deparseAppendStringInfoChar(state, '.');
+ }
+}
+
+// "fdw_options" in gram.y
+static void deparseFdwOptions(DeparseState *state, List *fdw_options)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, fdw_options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "HANDLER ");
+ deparseHandlerName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NO HANDLER ");
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "VALIDATOR ");
+ deparseHandlerName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NO VALIDATOR ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(fdw_options, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "type_list" in gram.y
+static void deparseTypeList(DeparseState *state, List *type_list)
+{
+ ListCell *lc = NULL;
+ foreach(lc, type_list)
+ {
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(type_list, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "opt_boolean_or_string" in gram.y
+static void deparseOptBooleanOrString(DeparseState *state, char *s)
+{
+ if (s == NULL)
+ return; // No value set
+ else if (strcmp(s, "true") == 0)
+ deparseAppendStringInfoString(state, "TRUE");
+ else if (strcmp(s, "false") == 0)
+ deparseAppendStringInfoString(state, "FALSE");
+ else if (strcmp(s, "on") == 0)
+ deparseAppendStringInfoString(state, "ON");
+ else if (strcmp(s, "off") == 0)
+ deparseAppendStringInfoString(state, "OFF");
+ else
+ deparseNonReservedWordOrSconst(state, s);
+}
+
+static void deparseOptBoolean(DeparseState *state, Node *node)
+{
+ if (node == NULL)
+ {
+ return;
+ }
+
+ switch (nodeTag(node))
+ {
+ case T_String:
+ deparseAppendStringInfo(state, " %s", strVal(node));
+ break;
+ case T_Integer:
+ deparseAppendStringInfo(state, " %d", intVal(node));
+ break;
+ case T_Boolean:
+ deparseAppendStringInfo(state, " %s", boolVal(node) ? "TRUE" : "FALSE");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+bool optBooleanValue(Node *node)
+{
+ if (node == NULL)
+ {
+ return true;
+ }
+
+ switch (nodeTag(node))
+ {
+ case T_String: {
+ // Longest valid string is "off\0"
+ char lower[4];
+ strncpy(lower, strVal(node), 4);
+ lower[3] = 0;
+
+ if (strcmp(lower, "on") == 0) {
+ return true;
+ } else if (strcmp(lower, "off") == 0) {
+ return false;
+ }
+
+ // No sane way to handle this.
+ return false;
+ }
+ case T_Integer:
+ return intVal(node) != 0;
+ case T_Boolean:
+ return boolVal(node);
+ default:
+ Assert(false);
+ return false;
+ }
+}
+
+// "var_name"
+//
+// Note this is kept separate from ColId in case we want to improve the
+// output of namespaced variable names
+static void deparseVarName(DeparseState *state, char *s)
+{
+ deparseColId(state, s);
+}
+
+// "var_list"
+static void deparseVarList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), ParamRef))
+ {
+ deparseParamRef(state, castNode(ParamRef, lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, lfirst(lc));
+ if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
+ deparseNumericOnly(state, (union ValUnion *) &a_const->val);
+ else if (IsA(&a_const->val, String))
+ deparseOptBooleanOrString(state, strVal(&a_const->val));
+ else
+ Assert(false);
+ }
+ else if (IsA(lfirst(lc), TypeCast))
+ {
+ deparseTypeCast(state, castNode(TypeCast, lfirst(lc)), DEPARSE_NODE_CONTEXT_SET_STATEMENT);
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "transaction_mode_list" in gram.y
+static void deparseTransactionModeList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "transaction_isolation") == 0)
+ {
+ char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
+ deparseAppendStringInfoString(state, "ISOLATION LEVEL ");
+ if (strcmp(s, "read uncommitted") == 0)
+ deparseAppendStringInfoString(state, "READ UNCOMMITTED");
+ else if (strcmp(s, "read committed") == 0)
+ deparseAppendStringInfoString(state, "READ COMMITTED");
+ else if (strcmp(s, "repeatable read") == 0)
+ deparseAppendStringInfoString(state, "REPEATABLE READ");
+ else if (strcmp(s, "serializable") == 0)
+ deparseAppendStringInfoString(state, "SERIALIZABLE");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ deparseAppendStringInfoString(state, "READ ONLY");
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ deparseAppendStringInfoString(state, "READ WRITE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ deparseAppendStringInfoString(state, "DEFERRABLE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ deparseAppendStringInfoString(state, "NOT DEFERRABLE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "alter_identity_column_option_list" in gram.y
+static void deparseAlterIdentityColumnOptionList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "RESTART ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "generated") == 0)
+ {
+ deparseAppendStringInfoString(state, "SET GENERATED ");
+ if (def_elem->arg == NULL)
+ elog(ERROR, "deparse: missing argument for identity generation specification");
+ if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
+ deparseAppendStringInfoString(state, "ALWAYS");
+ else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+ deparseAppendStringInfoString(state, "BY DEFAULT");
+ else
+ Assert(false);
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "SET ");
+ deparseSeqOptElem(state, def_elem);
+ }
+ if (lnext(l, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "reloptions" in gram.y
+static void deparseRelOptions(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (def_elem->defnamespace != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defnamespace));
+ deparseAppendStringInfoChar(state, '.');
+ }
+ if (def_elem->defname != NULL)
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ if (def_elem->defname != NULL && def_elem->arg != NULL)
+ deparseAppendStringInfoChar(state, '=');
+ if (def_elem->arg != NULL)
+ deparseDefArg(state, def_elem->arg, false);
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "OptWith" and "opt_reloptions" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptWith(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ deparseAppendStringInfoString(state, "WITH ");
+ deparseRelOptions(state, l);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "target_list" and "opt_target_list" in gram.y
+static void deparseTargetList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+
+ if (res_target->val == NULL)
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
+ else if (IsA(res_target->val, ColumnRef))
+ deparseColumnRef(state, castNode(ColumnRef, res_target->val));
+ else
+ deparseExpr(state, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (res_target->name != NULL) {
+ deparseAppendStringInfoString(state, " AS ");
+ deparseAppendStringInfoString(state, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ deparseAppendCommaAndPart(state);
+ }
+}
+
+// "insert_column_list" in gram.y
+static void deparseInsertColumnList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->name != NULL);
+ deparseAppendStringInfoString(state, quote_identifier(res_target->name));
+ deparseOptIndirection(state, res_target->indirection, 0);
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "xml_attribute_list" in gram.y
+static void deparseXmlAttributeList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ deparseExpr(state, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (res_target->name != NULL)
+ {
+ deparseAppendStringInfoString(state, " AS ");
+ deparseAppendStringInfoString(state, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "xml_namespace_list" in gram.y
+static void deparseXmlNamespaceList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (res_target->name == NULL)
+ deparseAppendStringInfoString(state, "DEFAULT ");
+
+ deparseExpr(state, res_target->val, DEPARSE_NODE_CONTEXT_NONE /* b_expr */);
+
+ if (res_target->name != NULL)
+ {
+ deparseAppendStringInfoString(state, " AS ");
+ deparseAppendStringInfoString(state, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "table_ref" in gram.y
+static void deparseTableRef(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_RangeVar:
+ deparseRangeVar(state, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_RangeTableSample:
+ deparseRangeTableSample(state, castNode(RangeTableSample, node));
+ break;
+ case T_RangeFunction:
+ deparseRangeFunction(state, castNode(RangeFunction, node));
+ break;
+ case T_RangeTableFunc:
+ deparseRangeTableFunc(state, castNode(RangeTableFunc, node));
+ break;
+ case T_RangeSubselect:
+ deparseRangeSubselect(state, castNode(RangeSubselect, node));
+ break;
+ case T_JoinExpr:
+ deparseJoinExpr(state, castNode(JoinExpr, node));
+ break;
+ case T_JsonTable:
+ deparseJsonTable(state, castNode(JsonTable, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "from_list" in gram.y
+static void deparseFromList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseTableRef(state, lfirst(lc));
+ if (lnext(l, lc))
+ deparseAppendCommaAndPart(state);
+ }
+}
+
+// "from_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseFromClause(DeparseState *state, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ deparseAppendPartGroup(state, "FROM", DEPARSE_PART_INDENT);
+ deparseFromList(state, l);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "where_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereClause(DeparseState *state, Node *node)
+{
+ if (node != NULL)
+ {
+ deparseAppendPartGroup(state, "WHERE", DEPARSE_PART_INDENT);
+ deparseExpr(state, node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "where_or_current_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereOrCurrentClause(DeparseState *state, Node *node)
+{
+ if (node == NULL)
+ return;
+
+ deparseAppendPartGroup(state, "WHERE", DEPARSE_PART_INDENT);
+
+ if (IsA(node, CurrentOfExpr)) {
+ CurrentOfExpr *current_of_expr = castNode(CurrentOfExpr, node);
+ deparseAppendStringInfoString(state, "CURRENT OF ");
+ deparseAppendStringInfoString(state, quote_identifier(current_of_expr->cursor_name));
+ } else {
+ deparseExpr(state, node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+}
+
+// "group_by_list" in gram.y
+static void deparseGroupByList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), GroupingSet))
+ deparseGroupingSet(state, castNode(GroupingSet, lfirst(lc)));
+ else
+ deparseExpr(state, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (lnext(l, lc))
+ deparseAppendCommaAndPart(state);
+ }
+}
+
+// "set_target" in gram.y
+static void deparseSetTarget(DeparseState *state, ResTarget *res_target)
+{
+ Assert(res_target->name != NULL);
+ deparseColId(state, res_target->name);
+ deparseOptIndirection(state, res_target->indirection, 0);
+}
+
+// "any_name_list" in gram.y
+static void deparseAnyNameList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseAnyName(state, castNode(List, lfirst(lc)));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "name_list" in gram.y
+static void deparseNameList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseColId(state, strVal(lfirst(lc)));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "opt_sort_clause" and "json_array_aggregate_order_by_clause_opt" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptSortClause(DeparseState *state, List *l, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_SELECT_SORT_CLAUSE)
+ deparseAppendPartGroup(state, "ORDER BY", DEPARSE_PART_INDENT_AND_MERGE);
+ else
+ deparseAppendStringInfoString(state, "ORDER BY ");
+
+ foreach(lc, l)
+ {
+ deparseSortBy(state, castNode(SortBy, lfirst(lc)));
+ if (lnext(l, lc))
+ {
+ if (context == DEPARSE_NODE_CONTEXT_SELECT_SORT_CLAUSE)
+ deparseAppendCommaAndPart(state);
+ else
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "func_arg_expr" in gram.y
+static void deparseFuncArgExpr(DeparseState *state, Node *node)
+{
+ if (IsA(node, NamedArgExpr))
+ {
+ NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
+ deparseAppendStringInfoString(state, named_arg_expr->name);
+ deparseAppendStringInfoString(state, " := ");
+ deparseExpr(state, (Node *) named_arg_expr->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ else
+ {
+ deparseExpr(state, node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+}
+
+// "set_clause_list" in gram.y
+static void deparseSetClauseList(DeparseState *state, List *target_list)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ int skip_next_n_elems = 0;
+
+ Assert(list_length(target_list) > 0);
+
+ foreach(lc, target_list)
+ {
+ if (skip_next_n_elems > 0)
+ {
+ skip_next_n_elems--;
+ continue;
+ }
+
+ if (foreach_current_index(lc) != 0)
+ deparseAppendCommaAndPart(state);
+
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (IsA(res_target->val, MultiAssignRef))
+ {
+ MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
+ deparseAppendStringInfoString(state, "(");
+ for_each_cell(lc2, target_list, lc)
+ {
+ deparseSetTarget(state, castNode(ResTarget, lfirst(lc2)));
+ if ((foreach_current_index(lc2) - foreach_current_index(lc)) == r->ncolumns - 1) // Last element in this multi-assign
+ break;
+ else if (lnext(target_list, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") = ");
+ deparseExpr(state, r->source, DEPARSE_NODE_CONTEXT_A_EXPR);
+ skip_next_n_elems = r->ncolumns - 1;
+ }
+ else
+ {
+ deparseSetTarget(state, res_target);
+ deparseAppendStringInfoString(state, " = ");
+ deparseExpr(state, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ }
+}
+
+// "func_expr_windowless" in gram.y
+static void deparseFuncExprWindowless(DeparseState *state, Node* node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(state, castNode(FuncCall, node), DEPARSE_NODE_CONTEXT_NONE /* we don't know which kind of expression */);
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(state, castNode(SQLValueFunction, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(state, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_FUNC_EXPR);
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(state, castNode(CoalesceExpr, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(state, castNode(MinMaxExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(state, castNode(XmlExpr, node), DEPARSE_NODE_CONTEXT_NONE /* we don't know which kind of expression */);
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(state, castNode(XmlSerialize, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "opt_collate" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptCollate(DeparseState *state, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ deparseAppendStringInfoString(state, "COLLATE ");
+ deparseAnyName(state, l);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "index_elem" in gram.y
+static void deparseIndexElem(DeparseState *state, IndexElem* index_elem)
+{
+ if (index_elem->name != NULL)
+ {
+ deparseColId(state, index_elem->name);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (index_elem->expr != NULL)
+ {
+ switch (nodeTag(index_elem->expr))
+ {
+ // Simple function calls can be written without wrapping parens
+ case T_FuncCall: // func_application
+ case T_SQLValueFunction: // func_expr_common_subexpr
+ case T_CoalesceExpr: // func_expr_common_subexpr
+ case T_MinMaxExpr: // func_expr_common_subexpr
+ case T_XmlExpr: // func_expr_common_subexpr
+ case T_XmlSerialize: // func_expr_common_subexpr
+ deparseFuncExprWindowless(state, index_elem->expr);
+ deparseAppendStringInfoString(state, " ");
+ break;
+ default:
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, index_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseOptCollate(state, index_elem->collation);
+
+ if (list_length(index_elem->opclass) > 0)
+ {
+ deparseAnyName(state, index_elem->opclass);
+
+ if (list_length(index_elem->opclassopts) > 0)
+ deparseRelOptions(state, index_elem->opclassopts);
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (index_elem->ordering)
+ {
+ case SORTBY_DEFAULT:
+ // Default
+ break;
+ case SORTBY_ASC:
+ deparseAppendStringInfoString(state, "ASC ");
+ break;
+ case SORTBY_DESC:
+ deparseAppendStringInfoString(state, "DESC ");
+ break;
+ case SORTBY_USING:
+ // Not allowed in CREATE INDEX
+ Assert(false);
+ break;
+ }
+
+ switch (index_elem->nulls_ordering)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ // Default
+ break;
+ case SORTBY_NULLS_FIRST:
+ deparseAppendStringInfoString(state, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ deparseAppendStringInfoString(state, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "qualified_name_list" in gram.y
+static void deparseQualifiedNameList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseRangeVar(state, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "OptInherit" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptInherit(DeparseState *state, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ deparseAppendStringInfoString(state, "INHERITS (");
+ deparseQualifiedNameList(state, l);
+ deparseAppendStringInfoString(state, ") ");
+ }
+}
+
+// "privilege_target" in gram.y
+static void deparsePrivilegeTarget(DeparseState *state, GrantTargetType targtype, ObjectType objtype, List *objs)
+{
+ switch (targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseQualifiedNameList(state, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ deparseQualifiedNameList(state, objs);
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "FOREIGN SERVER ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypesList(state, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypesList(state, objs);
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypesList(state, objs);
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ deparseAnyNameList(state, objs);
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECT ");
+ deparseNumericOnlyList(state, objs);
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseAnyNameList(state, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "ALL TABLES IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "ALL SEQUENCES IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "ALL FUNCTIONS IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "ALL PROCEDURES IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ALL ROUTINES IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_DEFAULTS: // defacl_privilege_target
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLES");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTIONS");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCES");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPES");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMAS");
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ }
+}
+
+// "opclass_item_list" in gram.y
+static void deparseOpclassItemList(DeparseState *state, List *items)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, items)
+ {
+ deparseCreateOpClassItem(state, castNode(CreateOpClassItem, lfirst(lc)));
+ if (lnext(items, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "createdb_opt_list" in gram.y
+static void deparseCreatedbOptList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "connection_limit") == 0)
+ deparseAppendStringInfoString(state, "CONNECTION LIMIT");
+ else
+ deparseGenericDefElemName(state, def_elem->defname);
+
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (def_elem->arg == NULL)
+ deparseAppendStringInfoString(state, "DEFAULT");
+ else if (IsA(def_elem->arg, Integer))
+ deparseSignedIconst(state, def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(state, strVal(def_elem->arg));
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "utility_option_list" in gram.y
+static void deparseUtilityOptionList(DeparseState *state, List *options)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ if (list_length(options) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(state, def_elem->defname);
+
+ if (def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(state, strVal(def_elem->arg));
+ else
+ Assert(false);
+ }
+
+ if (lnext(options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+}
+
+static void deparseSelectStmt(DeparseState *state, SelectStmt *stmt, DeparseNodeContext context)
+{
+ const ListCell *lc = NULL;
+ const ListCell *lc2 = NULL;
+ bool need_parens = context == DEPARSE_NODE_CONTEXT_SELECT_SETOP && (
+ list_length(stmt->sortClause) > 0 ||
+ stmt->limitOffset != NULL ||
+ stmt->limitCount != NULL ||
+ list_length(stmt->lockingClause) > 0 ||
+ stmt->withClause != NULL ||
+ stmt->op != SETOP_NONE);
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ if (need_parens)
+ {
+ deparseAppendPart(state, true);
+ deparseAppendStringInfoChar(state, '(');
+ }
+ if (need_parens || (context != DEPARSE_NODE_CONTEXT_SELECT_SETOP && context != DEPARSE_NODE_CONTEXT_INSERT_SELECT))
+ parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (stmt->withClause)
+ {
+ deparseWithClause(state, stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (stmt->op) {
+ case SETOP_NONE:
+ if (list_length(stmt->valuesLists) > 0)
+ {
+ const ListCell *lc;
+ deparseAppendPartGroup(state, "VALUES", DEPARSE_PART_INDENT_AND_MERGE);
+
+ foreach(lc, stmt->valuesLists)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseExprList(state, lfirst(lc));
+ deparseAppendStringInfoChar(state, ')');
+ if (lnext(stmt->valuesLists, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ }
+
+ deparseAppendPartGroup(state, "SELECT", DEPARSE_PART_INDENT_AND_MERGE);
+
+ if (list_length(stmt->targetList) > 0)
+ {
+ if (stmt->distinctClause != NULL)
+ {
+ deparseMarkCurrentPartNonMergable(state);
+ deparseAppendStringInfoString(state, "DISTINCT ");
+
+ if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
+ {
+ deparseAppendStringInfoString(state, "ON (");
+ deparseExprList(state, stmt->distinctClause);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ deparseAppendPart(state, true);
+ }
+
+ deparseTargetList(state, stmt->targetList);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (stmt->intoClause != NULL)
+ {
+ deparseAppendPartGroup(state, "INTO", DEPARSE_PART_INDENT);
+ deparseOptTemp(state, stmt->intoClause->rel->relpersistence);
+ deparseIntoClause(state, stmt->intoClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseFromClause(state, stmt->fromClause);
+ deparseWhereClause(state, stmt->whereClause);
+
+ if (list_length(stmt->groupClause) > 0)
+ {
+ deparseAppendPartGroup(state, "GROUP BY", DEPARSE_PART_INDENT_AND_MERGE);
+ if (stmt->groupDistinct)
+ deparseAppendStringInfoString(state, "DISTINCT ");
+ deparseGroupByList(state, stmt->groupClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (stmt->havingClause != NULL)
+ {
+ deparseAppendPartGroup(state, "HAVING", DEPARSE_PART_INDENT);
+ deparseExpr(state, stmt->havingClause, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (stmt->windowClause != NULL)
+ {
+ deparseAppendPartGroup(state, "WINDOW", DEPARSE_PART_INDENT);
+ foreach(lc, stmt->windowClause)
+ {
+ WindowDef *window_def = castNode(WindowDef, lfirst(lc));
+ Assert(window_def->name != NULL);
+ deparseAppendStringInfoString(state, window_def->name);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseWindowDef(state, window_def);
+ if (lnext(stmt->windowClause, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ break;
+ case SETOP_UNION:
+ case SETOP_INTERSECT:
+ case SETOP_EXCEPT:
+ {
+ deparseSelectStmt(state, stmt->larg, DEPARSE_NODE_CONTEXT_SELECT_SETOP);
+ switch (stmt->op)
+ {
+ case SETOP_UNION:
+ if (stmt->all)
+ deparseAppendPartGroup(state, "UNION ALL", DEPARSE_PART_NO_INDENT);
+ else
+ deparseAppendPartGroup(state, "UNION", DEPARSE_PART_NO_INDENT);
+ break;
+ case SETOP_INTERSECT:
+ if (stmt->all)
+ deparseAppendPartGroup(state, "INTERSECT ALL", DEPARSE_PART_NO_INDENT);
+ else
+ deparseAppendPartGroup(state, "INTERSECT", DEPARSE_PART_NO_INDENT);
+ break;
+ case SETOP_EXCEPT:
+ if (stmt->all)
+ deparseAppendPartGroup(state, "EXCEPT ALL", DEPARSE_PART_NO_INDENT);
+ else
+ deparseAppendPartGroup(state, "EXCEPT", DEPARSE_PART_NO_INDENT);
+ break;
+ default:
+ Assert(false);
+ }
+ deparseAppendPart(state, true);
+ deparseSelectStmt(state, stmt->rarg, DEPARSE_NODE_CONTEXT_SELECT_SETOP);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ break;
+ }
+
+ deparseOptSortClause(state, stmt->sortClause, DEPARSE_NODE_CONTEXT_SELECT_SORT_CLAUSE);
+
+ if (stmt->limitCount != NULL)
+ {
+ if (stmt->limitOption == LIMIT_OPTION_COUNT)
+ deparseAppendPartGroup(state, "LIMIT", DEPARSE_PART_INDENT);
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ deparseAppendStringInfoString(state, "FETCH FIRST ");
+
+ if (IsA(stmt->limitCount, A_Const) && castNode(A_Const, stmt->limitCount)->isnull)
+ deparseAppendStringInfoString(state, "ALL");
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ deparseCExpr(state, stmt->limitCount);
+ else
+ deparseExpr(state, stmt->limitCount, DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ deparseAppendStringInfoString(state, "ROWS WITH TIES ");
+ }
+
+ if (stmt->limitOffset != NULL)
+ {
+ deparseAppendPartGroup(state, "OFFSET", DEPARSE_PART_INDENT);
+ deparseExpr(state, stmt->limitOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(stmt->lockingClause) > 0)
+ {
+ foreach(lc, stmt->lockingClause)
+ {
+ deparseLockingClause(state, castNode(LockingClause, lfirst(lc)));
+ if (lnext(stmt->lockingClause, lc))
+ deparseAppendStringInfoString(state, " ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+
+ /* Note that parent_level can be NULL, so we repeat the full if condition here */
+ if (need_parens || (context != DEPARSE_NODE_CONTEXT_SELECT_SETOP && context != DEPARSE_NODE_CONTEXT_INSERT_SELECT))
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseIntoClause(DeparseState *state, IntoClause *into_clause)
+{
+ ListCell *lc;
+
+ deparseRangeVar(state, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE); /* target relation name */
+
+ if (list_length(into_clause->colNames) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, into_clause->colNames);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (into_clause->accessMethod != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(into_clause->accessMethod));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseOptWith(state, into_clause->options);
+
+ switch (into_clause->onCommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ deparseAppendStringInfoString(state, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ deparseAppendStringInfoString(state, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ deparseAppendStringInfoString(state, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (into_clause->tableSpaceName != NULL)
+ {
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseAppendStringInfoString(state, quote_identifier(into_clause->tableSpaceName));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseRangeVar(DeparseState *state, RangeVar *range_var, DeparseNodeContext context)
+{
+ if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ deparseAppendStringInfoString(state, "ONLY ");
+
+ if (range_var->catalogname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(range_var->catalogname));
+ deparseAppendStringInfoChar(state, '.');
+ }
+
+ if (range_var->schemaname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(range_var->schemaname));
+ deparseAppendStringInfoChar(state, '.');
+ }
+
+ Assert(range_var->relname != NULL);
+ deparseAppendStringInfoString(state, quote_identifier(range_var->relname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (range_var->alias != NULL)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
+ deparseAppendStringInfoString(state, "AS ");
+ deparseAlias(state, range_var->alias);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+void deparseRawStmt(StringInfo str, struct RawStmt *raw_stmt)
+{
+ PostgresDeparseOpts opts;
+ MemSet(&opts, 0, sizeof(PostgresDeparseOpts)); // zero initialized means pretty print = false
+ deparseRawStmtOpts(str, raw_stmt, opts);
+}
+
+void deparseRawStmtOpts(StringInfo str, struct RawStmt *raw_stmt, PostgresDeparseOpts opts)
+{
+ DeparseState *state = NULL;
+ if (raw_stmt->stmt == NULL)
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
+
+ state = palloc0(sizeof(DeparseState));
+ state->opts = opts;
+ if (state->opts.indent_size == 0)
+ state->opts.indent_size = 4;
+ if (state->opts.max_line_length == 0)
+ state->opts.max_line_length = 80;
+
+ /* Check for any comments at the start of the statement */
+ if (state->opts.comment_count > 0)
+ {
+ /*
+ * Filter out comments that are placed before this statement starts, this
+ * avoids emitting comments multiple times in multi-statement queries.
+ */
+ for (int i = 0; i < state->opts.comment_count; i++)
+ {
+ if (state->opts.comments[i]->match_location < raw_stmt->stmt_location)
+ state->emitted_comments = bms_add_member(state->emitted_comments, i);
+ }
+
+ deparseStateIncreaseNestingLevel(state);
+ deparseAppendCommentsIfNeeded(state, raw_stmt->stmt_location);
+ deparseRemoveTrailingEmptyPart(state);
+ deparseStateDecreaseNestingLevel(state, NULL);
+ }
+
+ deparseStmt(state, raw_stmt->stmt);
+
+ deparseEmit(state, str);
+
+ bms_free(state->emitted_comments);
+ pfree(state);
+}
+
+static void deparseAlias(DeparseState *state, Alias *alias)
+{
+ deparseAppendStringInfoString(state, quote_identifier(alias->aliasname));
+
+ if (list_length(alias->colnames) > 0)
+ {
+ const ListCell *lc = NULL;
+ deparseAppendStringInfoChar(state, '(');
+ deparseNameList(state, alias->colnames);
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+static void deparseAConst(DeparseState *state, A_Const *a_const)
+{
+ union ValUnion *val = a_const->isnull ? NULL : &a_const->val;
+ deparseAppendCommentsIfNeeded(state, a_const->location);
+ deparseValue(state, val, DEPARSE_NODE_CONTEXT_CONSTANT);
+}
+
+static void deparseFuncCall(DeparseState *state, FuncCall *func_call, DeparseNodeContext context)
+{
+ const ListCell *lc = NULL;
+
+ Assert(list_length(func_call->funcname) > 0);
+
+ if (list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ deparseAppendStringInfoString(state, "OVERLAY(");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " PLACING ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseExpr(state, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FOR ");
+ deparseExpr(state, lfourth(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "substring") == 0)
+ {
+ /*
+ * "SUBSTRING" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.substring)
+ */
+ Assert(list_length(func_call->args) == 2 || list_length(func_call->args) == 3);
+ deparseAppendStringInfoString(state, "SUBSTRING(");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (list_length(func_call->args) == 3)
+ {
+ deparseAppendStringInfoString(state, " FOR ");
+ deparseExpr(state, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "position") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "POSITION" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.position)
+ * Note that the first and second arguments are switched in this format
+ */
+ deparseAppendStringInfoString(state, "POSITION(");
+ deparseBExpr(state, lsecond(func_call->args));
+ deparseAppendStringInfoString(state, " IN ");
+ deparseBExpr(state, linitial(func_call->args));
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 3)
+ {
+ /*
+ * "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ deparseAppendStringInfoString(state, "overlay(");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " placing ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " from ");
+ deparseExpr(state, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "pg_collation_for") == 0 &&
+ list_length(func_call->args) == 1)
+ {
+ /*
+ * "collation for" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ deparseAppendStringInfoString(state, "collation for (");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "extract") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "EXTRACT" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.extract)
+ */
+ deparseAppendStringInfoString(state, "extract (");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlaps") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * "OVERLAPS" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlaps)
+ * format: (start_1, end_1) overlaps (start_2, end_2)
+ */
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+
+ deparseAppendStringInfoString(state, "overlaps ");
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, lfourth(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ (
+ strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0
+ ))
+ {
+ /*
+ * "TRIM " is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.ltrim)
+ * Note that the first and second arguments are switched in this format
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ deparseAppendStringInfoString(state, "TRIM (");
+ if (strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0)
+ deparseAppendStringInfoString(state, "LEADING ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0)
+ deparseAppendStringInfoString(state, "BOTH ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0)
+ deparseAppendStringInfoString(state, "TRAILING ");
+
+ if (list_length(func_call->args) == 2)
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "timezone") == 0 &&
+ list_length(func_call->args) > 0 &&
+ list_length(func_call->args) <= 2)
+ {
+ /*
+ * "AT TIME ZONE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.timezone)
+ * Note that the arguments are swapped in this case
+ */
+ Expr* e;
+ bool isLocal = list_length(func_call->args) == 1;
+
+ if (isLocal)
+ e = linitial(func_call->args);
+ else
+ e = lsecond(func_call->args);
+
+ // If we're not inside an a_expr context, we must add wrapping parenthesis around the AT ... syntax
+ if (context != DEPARSE_NODE_CONTEXT_A_EXPR) {
+ deparseAppendStringInfoChar(state, '(');
+ }
+
+ if (IsA(e, A_Expr)) {
+ deparseAppendStringInfoChar(state, '(');
+ }
+
+ deparseExpr(state, (Node*) e, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (IsA(e, A_Expr)) {
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ if (isLocal)
+ deparseAppendStringInfoString(state, " AT LOCAL");
+ else {
+ deparseAppendStringInfoString(state, " AT TIME ZONE ");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+
+ if (context != DEPARSE_NODE_CONTEXT_A_EXPR) {
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "normalize") == 0)
+ {
+ /*
+ * "NORMALIZE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.normalize)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ deparseAppendStringInfoString(state, "normalize (");
+
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (list_length(func_call->args) == 2)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(state, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "is_normalized") == 0)
+ {
+ /*
+ * "IS NORMALIZED" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.is_normalized)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " IS ");
+ if (list_length(func_call->args) == 2)
+ {
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(state, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ deparseAppendStringInfoString(state, " NORMALIZED ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "xmlexists") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ deparseAppendStringInfoString(state, "xmlexists (");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+ deparseAppendStringInfoString(state, " PASSING ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "system_user") == 0)
+ {
+ deparseAppendStringInfoString(state, "SYSTEM_USER");
+ return;
+ }
+
+ deparseFuncName(state, func_call->funcname);
+ deparseAppendStringInfoChar(state, '(');
+
+ if (func_call->agg_distinct)
+ deparseAppendStringInfoString(state, "DISTINCT ");
+
+ if (func_call->agg_star)
+ {
+ deparseAppendStringInfoChar(state, '*');
+ }
+ else if (list_length(func_call->args) > 0)
+ {
+ foreach(lc, func_call->args)
+ {
+ if (func_call->func_variadic && !lnext(func_call->args, lc))
+ deparseAppendStringInfoString(state, "VARIADIC ");
+ deparseFuncArgExpr(state, lfirst(lc));
+ if (lnext(func_call->args, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (func_call->agg_order != NULL && !func_call->agg_within_group)
+ {
+ deparseOptSortClause(state, func_call->agg_order, DEPARSE_NODE_CONTEXT_NONE);
+ }
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (func_call->agg_order != NULL && func_call->agg_within_group)
+ {
+ deparseAppendStringInfoString(state, "WITHIN GROUP (");
+ deparseOptSortClause(state, func_call->agg_order, DEPARSE_NODE_CONTEXT_NONE);
+ removeTrailingSpace(state);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (func_call->agg_filter)
+ {
+ deparseAppendStringInfoString(state, "FILTER (WHERE ");
+ deparseExpr(state, func_call->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (func_call->over)
+ {
+ deparseAppendStringInfoString(state, "OVER ");
+ if (func_call->over->name)
+ deparseAppendStringInfoString(state, func_call->over->name);
+ else
+ deparseWindowDef(state, func_call->over);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseWindowDef(DeparseState *state, WindowDef* window_def)
+{
+ ListCell *lc;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ // The parent node is responsible for outputting window_def->name
+
+ // Special case completely empty window clauses and return early
+ if (!window_def->refname && list_length(window_def->partitionClause) == 0 &&
+ list_length(window_def->orderClause) == 0 &&
+ !(window_def->frameOptions & FRAMEOPTION_NONDEFAULT))
+ {
+ deparseAppendStringInfoString(state, "()");
+ return;
+ }
+
+ deparseAppendStringInfoChar(state, '(');
+ parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (window_def->refname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(window_def->refname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(window_def->partitionClause) > 0)
+ {
+ deparseAppendStringInfoString(state, "PARTITION BY ");
+ deparseExprList(state, window_def->partitionClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+ deparseAppendPart(state, true);
+ deparseOptSortClause(state, window_def->orderClause, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
+ {
+ deparseAppendPartGroup(state, NULL, DEPARSE_PART_NO_INDENT);
+ if (window_def->frameOptions & FRAMEOPTION_RANGE)
+ deparseAppendStringInfoString(state, "RANGE ");
+ else if (window_def->frameOptions & FRAMEOPTION_ROWS)
+ deparseAppendStringInfoString(state, "ROWS ");
+ else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
+ deparseAppendStringInfoString(state, "GROUPS ");
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ deparseAppendStringInfoString(state, "BETWEEN ");
+
+ // frame_start
+ if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ {
+ deparseAppendStringInfoString(state, "UNBOUNDED PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
+ {
+ deparseAppendStringInfoString(state, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(state, window_def->startOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(state, window_def->startOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FOLLOWING ");
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ {
+ deparseAppendStringInfoString(state, "AND ");
+
+ // frame_end
+ if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
+ {
+ deparseAppendStringInfoString(state, "UNBOUNDED FOLLOWING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
+ {
+ deparseAppendStringInfoString(state, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(state, window_def->endOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(state, window_def->endOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FOLLOWING ");
+ }
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
+ deparseAppendStringInfoString(state, "EXCLUDE CURRENT ROW ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
+ deparseAppendStringInfoString(state, "EXCLUDE GROUP ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
+ deparseAppendStringInfoString(state, "EXCLUDE TIES ");
+ }
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseColumnRef(DeparseState *state, ColumnRef* column_ref)
+{
+ Assert(list_length(column_ref->fields) >= 1);
+
+ deparseAppendCommentsIfNeeded(state, column_ref->location);
+
+ if (IsA(linitial(column_ref->fields), A_Star))
+ deparseAStar(state, castNode(A_Star, linitial(column_ref->fields)));
+ else if (IsA(linitial(column_ref->fields), String))
+ deparseColLabel(state, strVal(linitial(column_ref->fields)));
+
+ deparseOptIndirection(state, column_ref->fields, 1);
+}
+
+static void deparseSubLink(DeparseState *state, SubLink* sub_link)
+{
+ switch (sub_link->subLinkType) {
+ case EXISTS_SUBLINK:
+ deparseAppendStringInfoString(state, "EXISTS (");
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case ALL_SUBLINK:
+ deparseExpr(state, sub_link->testexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseSubqueryOp(state, sub_link->operName);
+ deparseAppendStringInfoString(state, " ALL (");
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case ANY_SUBLINK:
+ deparseExpr(state, sub_link->testexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (list_length(sub_link->operName) > 0)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseSubqueryOp(state, sub_link->operName);
+ deparseAppendStringInfoString(state, " ANY ");
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, " IN ");
+ }
+ deparseAppendStringInfoChar(state, '(');
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case ROWCOMPARE_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case EXPR_SUBLINK:
+ deparseAppendStringInfoString(state, "(");
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case MULTIEXPR_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case ARRAY_SUBLINK:
+ deparseAppendStringInfoString(state, "ARRAY(");
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case CTE_SUBLINK: /* for SubPlans only */
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ }
+}
+
+// Checks whether a node needs parens when used in a "b_expr" context (because the node is handled by the "a_expr" rule in gram.y)
+static bool
+needsParensAsBExpr(Node *node)
+{
+ if (node == NULL)
+ return false;
+ return IsA(node, BoolExpr) || IsA(node, BooleanTest) || IsA(node, NullTest) || IsA(node, A_Expr);
+}
+
+// This handles "A_Expr" parse tree objects, which are a subset of the rules in "a_expr" (handled by deparseExpr)
+static void deparseAExpr(DeparseState *state, A_Expr* a_expr, DeparseNodeContext context)
+{
+ ListCell *lc;
+ char *name;
+
+ bool need_lexpr_parens = needsParensAsBExpr(a_expr->lexpr);
+ bool need_rexpr_parens = needsParensAsBExpr(a_expr->rexpr);
+
+ switch (a_expr->kind) {
+ case AEXPR_OP: /* normal operator */
+ {
+ if (a_expr->lexpr != NULL)
+ {
+ if (need_lexpr_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, a_expr->lexpr, context);
+ if (need_lexpr_parens)
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ deparseQualOp(state, a_expr->name);
+ if (a_expr->rexpr != NULL)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ if (need_rexpr_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, a_expr->rexpr, context);
+ if (need_rexpr_parens)
+ deparseAppendStringInfoChar(state, ')');
+ }
+ }
+ return;
+ case AEXPR_OP_ANY: /* scalar op ANY (array) */
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseSubqueryOp(state, a_expr->name);
+ deparseAppendStringInfoString(state, " ANY(");
+ deparseExpr(state, a_expr->rexpr, context);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_OP_ALL: /* scalar op ALL (array) */
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseSubqueryOp(state, a_expr->name);
+ deparseAppendStringInfoString(state, " ALL(");
+ deparseExpr(state, a_expr->rexpr, context);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ if (need_lexpr_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, a_expr->lexpr, context);
+ if (need_lexpr_parens)
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoString(state, " IS DISTINCT FROM ");
+ if (need_rexpr_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, a_expr->rexpr, context);
+ if (need_rexpr_parens)
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoString(state, " IS NOT DISTINCT FROM ");
+ deparseExpr(state, a_expr->rexpr, context);
+ return;
+ case AEXPR_NULLIF: /* NULLIF - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseAppendStringInfoString(state, "NULLIF(");
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, a_expr->rexpr, context);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "=") == 0) {
+ deparseAppendStringInfoString(state, "IN ");
+ } else if (strcmp(name, "<>") == 0) {
+ deparseAppendStringInfoString(state, "NOT IN ");
+ } else {
+ Assert(false);
+ }
+ deparseAppendStringInfoChar(state, '(');
+ if (IsA(a_expr->rexpr, SubLink))
+ deparseSubLink(state, castNode(SubLink, a_expr->rexpr));
+ else
+ deparseExprList(state, castNode(List, a_expr->rexpr));
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~~") == 0) {
+ deparseAppendStringInfoString(state, "LIKE ");
+ } else if (strcmp(name, "!~~") == 0) {
+ deparseAppendStringInfoString(state, "NOT LIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(state, a_expr->rexpr, context);
+ return;
+ case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~~*") == 0) {
+ deparseAppendStringInfoString(state, "ILIKE ");
+ } else if (strcmp(name, "!~~*") == 0) {
+ deparseAppendStringInfoString(state, "NOT ILIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(state, a_expr->rexpr, context);
+ return;
+ case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~") == 0) {
+ deparseAppendStringInfoString(state, "SIMILAR TO ");
+ } else if (strcmp(name, "!~") == 0) {
+ deparseAppendStringInfoString(state, "NOT SIMILAR TO ");
+ } else {
+ Assert(false);
+ }
+
+ FuncCall *n = castNode(FuncCall, a_expr->rexpr);
+ Assert(list_length(n->funcname) == 2);
+ Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
+ Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
+ Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
+
+ deparseExpr(state, linitial(n->args), context);
+ if (list_length(n->args) == 2)
+ {
+ deparseAppendStringInfoString(state, " ESCAPE ");
+ deparseExpr(state, lsecond(n->args), context);
+ }
+
+ return;
+ case AEXPR_BETWEEN: /* name must be "BETWEEN" */
+ case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
+ case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
+ case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseAppendStringInfoString(state, strVal(linitial(a_expr->name)));
+ deparseAppendStringInfoChar(state, ' ');
+
+ foreach(lc, castNode(List, a_expr->rexpr)) {
+ deparseExpr(state, lfirst(lc), context);
+ if (lnext(castNode(List, a_expr->rexpr), lc))
+ deparseAppendStringInfoString(state, " AND ");
+ }
+ return;
+ }
+}
+
+static void deparseBoolExpr(DeparseState *state, BoolExpr *bool_expr)
+{
+ const ListCell *lc = NULL;
+ switch (bool_expr->boolop)
+ {
+ case AND_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseExpr(state, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ if (lnext(bool_expr->args, lc))
+ {
+ deparseAppendPart(state, true);
+ deparseAppendStringInfoString(state, "AND ");
+ }
+ }
+ return;
+ case OR_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseExpr(state, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ if (lnext(bool_expr->args, lc))
+ deparseAppendStringInfoString(state, " OR ");
+ }
+ return;
+ case NOT_EXPR:
+ Assert(list_length(bool_expr->args) == 1);
+ bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
+ deparseAppendStringInfoString(state, "NOT ");
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, linitial(bool_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ }
+}
+
+static void deparseAStar(DeparseState *state, A_Star *a_star)
+{
+ deparseAppendStringInfoChar(state, '*');
+}
+
+static void deparseCollateClause(DeparseState *state, CollateClause* collate_clause)
+{
+ ListCell *lc;
+ if (collate_clause->arg != NULL)
+ {
+ bool need_parens = IsA(collate_clause->arg, A_Expr);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, collate_clause->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ deparseAppendStringInfoString(state, "COLLATE ");
+ deparseAnyName(state, collate_clause->collname);
+}
+
+// "sortby" in gram.y
+static void deparseSortBy(DeparseState *state, SortBy* sort_by)
+{
+ deparseExpr(state, sort_by->node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (sort_by->sortby_dir)
+ {
+ case SORTBY_DEFAULT:
+ break;
+ case SORTBY_ASC:
+ deparseAppendStringInfoString(state, "ASC ");
+ break;
+ case SORTBY_DESC:
+ deparseAppendStringInfoString(state, "DESC ");
+ break;
+ case SORTBY_USING:
+ deparseAppendStringInfoString(state, "USING ");
+ deparseQualOp(state, sort_by->useOp);
+ break;
+ }
+
+ switch (sort_by->sortby_nulls)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ break;
+ case SORTBY_NULLS_FIRST:
+ deparseAppendStringInfoString(state, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ deparseAppendStringInfoString(state, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseParamRef(DeparseState *state, ParamRef* param_ref)
+{
+ if (param_ref->number == 0) {
+ deparseAppendStringInfoChar(state, '?');
+ } else {
+ deparseAppendStringInfo(state, "$%d", param_ref->number);
+ }
+}
+
+static void deparseSQLValueFunction(DeparseState *state, SQLValueFunction* sql_value_function)
+{
+ switch (sql_value_function->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ deparseAppendStringInfoString(state, "current_date");
+ break;
+ case SVFOP_CURRENT_TIME:
+ deparseAppendStringInfoString(state, "current_time");
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ deparseAppendStringInfoString(state, "current_time"); // with precision
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ deparseAppendStringInfoString(state, "current_timestamp");
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ deparseAppendStringInfoString(state, "current_timestamp"); // with precision
+ break;
+ case SVFOP_LOCALTIME:
+ deparseAppendStringInfoString(state, "localtime");
+ break;
+ case SVFOP_LOCALTIME_N:
+ deparseAppendStringInfoString(state, "localtime"); // with precision
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ deparseAppendStringInfoString(state, "localtimestamp");
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ deparseAppendStringInfoString(state, "localtimestamp"); // with precision
+ break;
+ case SVFOP_CURRENT_ROLE:
+ deparseAppendStringInfoString(state, "current_role");
+ break;
+ case SVFOP_CURRENT_USER:
+ deparseAppendStringInfoString(state, "current_user");
+ break;
+ case SVFOP_USER:
+ deparseAppendStringInfoString(state, "user");
+ break;
+ case SVFOP_SESSION_USER:
+ deparseAppendStringInfoString(state, "session_user");
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ deparseAppendStringInfoString(state, "current_catalog");
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ deparseAppendStringInfoString(state, "current_schema");
+ break;
+ }
+
+ if (sql_value_function->typmod != -1)
+ {
+ deparseAppendStringInfo(state, "(%d)", sql_value_function->typmod);
+ }
+}
+
+static void deparseWithClause(DeparseState *state, WithClause *with_clause)
+{
+ ListCell *lc;
+
+ deparseAppendPartGroup(state, "WITH", DEPARSE_PART_NO_INDENT);
+ if (with_clause->recursive)
+ deparseAppendStringInfoString(state, "RECURSIVE ");
+
+ foreach(lc, with_clause->ctes) {
+ deparseCommonTableExpr(state, castNode(CommonTableExpr, lfirst(lc)));
+ if (lnext(with_clause->ctes, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "joined_table" in gram.y
+static void deparseJoinExpr(DeparseState *state, JoinExpr *join_expr)
+{
+ ListCell *lc;
+ bool need_alias_parens = join_expr->alias != NULL;
+ bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
+
+ if (need_alias_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseTableRef(state, join_expr->larg);
+ deparseAppendPart(state, true);
+
+ if (join_expr->isNatural)
+ deparseAppendStringInfoString(state, "NATURAL ");
+
+ switch (join_expr->jointype)
+ {
+ case JOIN_INNER: /* matching tuple pairs only */
+ if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
+ deparseAppendStringInfoString(state, "CROSS ");
+ break;
+ case JOIN_LEFT: /* pairs + unmatched LHS tuples */
+ deparseAppendStringInfoString(state, "LEFT ");
+ break;
+ case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
+ deparseAppendStringInfoString(state, "FULL ");
+ break;
+ case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
+ deparseAppendStringInfoString(state, "RIGHT ");
+ break;
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ case JOIN_RIGHT_ANTI:
+ case JOIN_UNIQUE_OUTER:
+ case JOIN_UNIQUE_INNER:
+ // Only used by the planner/executor, not seen in parser output
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "JOIN ");
+
+ if (need_rarg_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseTableRef(state, join_expr->rarg);
+ if (need_rarg_parens)
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (join_expr->quals != NULL)
+ {
+ deparseAppendStringInfoString(state, "ON ");
+ deparseExpr(state, join_expr->quals, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(join_expr->usingClause) > 0)
+ {
+ deparseAppendStringInfoString(state, "USING (");
+ deparseNameList(state, join_expr->usingClause);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (join_expr->join_using_alias)
+ {
+ deparseAppendStringInfoString(state, "AS ");
+ deparseAppendStringInfoString(state, join_expr->join_using_alias->aliasname);
+ }
+ }
+
+ if (need_alias_parens)
+ deparseAppendStringInfoString(state, ") ");
+
+ if (join_expr->alias != NULL)
+ deparseAlias(state, join_expr->alias);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCTESearchClause(DeparseState *state, CTESearchClause *search_clause)
+{
+ deparseAppendStringInfoString(state, " SEARCH ");
+ if (search_clause->search_breadth_first)
+ deparseAppendStringInfoString(state, "BREADTH ");
+ else
+ deparseAppendStringInfoString(state, "DEPTH ");
+
+ deparseAppendStringInfoString(state, "FIRST BY ");
+
+ if (search_clause->search_col_list)
+ deparseColumnList(state, search_clause->search_col_list);
+
+ deparseAppendStringInfoString(state, " SET ");
+ deparseAppendStringInfoString(state, quote_identifier(search_clause->search_seq_column));
+}
+
+// "opt_cycle_clause" in gram.y
+static void deparseCTECycleClause(DeparseState *state, CTECycleClause *cycle_clause)
+{
+ deparseAppendStringInfoString(state, " CYCLE ");
+
+ if (cycle_clause->cycle_col_list)
+ deparseColumnList(state, cycle_clause->cycle_col_list);
+
+ deparseAppendStringInfoString(state, " SET ");
+ deparseAppendStringInfoString(state, quote_identifier(cycle_clause->cycle_mark_column));
+
+ if (cycle_clause->cycle_mark_value)
+ {
+ deparseAppendStringInfoString(state, " TO ");
+ deparseAexprConst(state, cycle_clause->cycle_mark_value);
+ }
+
+ if (cycle_clause->cycle_mark_default)
+ {
+ deparseAppendStringInfoString(state, " DEFAULT ");
+ deparseAexprConst(state, cycle_clause->cycle_mark_default);
+ }
+
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(cycle_clause->cycle_path_column));
+}
+
+static void deparseCommonTableExpr(DeparseState *state, CommonTableExpr *cte)
+{
+ deparseAppendCommentsIfNeeded(state, cte->location);
+
+ deparseColId(state, cte->ctename);
+
+ if (list_length(cte->aliascolnames) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseNameList(state, cte->aliascolnames);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "AS ");
+ switch (cte->ctematerialized) {
+ case CTEMaterializeDefault: /* no option specified */
+ break;
+ case CTEMaterializeAlways:
+ deparseAppendStringInfoString(state, "MATERIALIZED ");
+ break;
+ case CTEMaterializeNever:
+ deparseAppendStringInfoString(state, "NOT MATERIALIZED ");
+ break;
+ }
+
+ deparseAppendStringInfoChar(state, '(');
+ deparsePreparableStmt(state, cte->ctequery);
+ deparseAppendStringInfoChar(state, ')');
+
+ if (cte->search_clause)
+ deparseCTESearchClause(state, cte->search_clause);
+ if (cte->cycle_clause)
+ deparseCTECycleClause(state, cte->cycle_clause);
+}
+
+static void deparseRangeSubselect(DeparseState *state, RangeSubselect *range_subselect)
+{
+ if (range_subselect->lateral)
+ deparseAppendStringInfoString(state, "LATERAL ");
+
+ deparseAppendStringInfoChar(state, '(');
+ deparseSelectStmt(state, castNode(SelectStmt, range_subselect->subquery), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+
+ if (range_subselect->alias != NULL)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseAlias(state, range_subselect->alias);
+ }
+}
+
+static void deparseRangeFunction(DeparseState *state, RangeFunction *range_func)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (range_func->lateral)
+ deparseAppendStringInfoString(state, "LATERAL ");
+
+ if (range_func->is_rowsfrom)
+ {
+ deparseAppendStringInfoString(state, "ROWS FROM ");
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, range_func->functions)
+ {
+ List *lfunc = castNode(List, lfirst(lc));
+ Assert(list_length(lfunc) == 2);
+ deparseFuncExprWindowless(state, linitial(lfunc));
+ deparseAppendStringInfoChar(state, ' ');
+ List *coldeflist = castNode(List, lsecond(lfunc));
+ if (list_length(coldeflist) > 0)
+ {
+ deparseAppendStringInfoString(state, "AS (");
+ foreach(lc2, coldeflist)
+ {
+ deparseColumnDef(state, castNode(ColumnDef, lfirst(lc2)));
+ if (lnext(coldeflist, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+ if (lnext(range_func->functions, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+ else
+ {
+ Assert(list_length(linitial(range_func->functions)) == 2);
+ deparseFuncExprWindowless(state, linitial(linitial(range_func->functions)));
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (range_func->ordinality)
+ deparseAppendStringInfoString(state, "WITH ORDINALITY ");
+
+ if (range_func->alias != NULL)
+ {
+ deparseAlias(state, range_func->alias);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(range_func->coldeflist) > 0)
+ {
+ if (range_func->alias == NULL)
+ deparseAppendStringInfoString(state, "AS ");
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, range_func->coldeflist)
+ {
+ deparseColumnDef(state, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(range_func->coldeflist, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAArrayExpr(DeparseState *state, A_ArrayExpr *array_expr)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ARRAY[");
+ deparseExprList(state, array_expr->elements);
+ deparseAppendStringInfoChar(state, ']');
+}
+
+static void deparseRowExpr(DeparseState *state, RowExpr *row_expr)
+{
+ ListCell *lc;
+
+ switch (row_expr->row_format)
+ {
+ case COERCE_EXPLICIT_CALL:
+ deparseAppendStringInfoString(state, "ROW");
+ break;
+ case COERCE_SQL_SYNTAX:
+ case COERCE_EXPLICIT_CAST:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCE_IMPLICIT_CAST:
+ // No prefix
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "(");
+ deparseExprList(state, row_expr->args);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseTypeCast(DeparseState *state, TypeCast *type_cast, DeparseNodeContext context)
+{
+ bool need_parens = needsParensAsBExpr(type_cast->arg);
+
+ Assert(type_cast->typeName != NULL);
+
+ if (context == DEPARSE_NODE_CONTEXT_FUNC_EXPR)
+ {
+ deparseAppendStringInfoString(state, "CAST(");
+ deparseExpr(state, type_cast->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, type_cast->typeName);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ }
+
+ if (IsA(type_cast->arg, A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, type_cast->arg);
+
+ if (list_length(type_cast->typeName->names) == 2 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
+ {
+ char *typename = strVal(lsecond(type_cast->typeName->names));
+ if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
+ {
+ deparseAppendStringInfoString(state, "char ");
+ deparseAConst(state, a_const);
+ return;
+ }
+ else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
+ {
+ /*
+ * Handle "bool" or "false" in the statement, which is represented as a typecast
+ * (other boolean casts should be represented as a cast, i.e. don't need special handling)
+ */
+ char *const_val = strVal(&a_const->val);
+ if (strcmp(const_val, "t") == 0)
+ {
+ deparseAppendStringInfoString(state, "true");
+ return;
+ }
+ if (strcmp(const_val, "f") == 0)
+ {
+ deparseAppendStringInfoString(state, "false");
+ return;
+ }
+ }
+ else if (strcmp(typename, "interval") == 0 && context == DEPARSE_NODE_CONTEXT_SET_STATEMENT && IsA(&a_const->val, String))
+ {
+ deparseAppendStringInfoString(state, "interval ");
+ deparseAConst(state, a_const);
+ deparseIntervalTypmods(state, type_cast->typeName);
+ return;
+ }
+ }
+
+ // Ensure negative values have wrapping parentheses
+ if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
+ {
+ need_parens = true;
+ }
+
+ if (list_length(type_cast->typeName->names) == 1 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "point") == 0 &&
+ a_const->location > type_cast->typeName->location)
+ {
+ deparseAppendStringInfoString(state, " point ");
+ deparseAConst(state, a_const);
+ return;
+ }
+ }
+
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, type_cast->arg, DEPARSE_NODE_CONTEXT_NONE /* could be either a_expr or b_expr (we could pass this down, but that'd require two kinds of contexts most likely) */);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ deparseAppendStringInfoString(state, "::");
+ deparseTypeName(state, type_cast->typeName);
+}
+
+static void deparseTypeName(DeparseState *state, TypeName *type_name)
+{
+ ListCell *lc;
+ bool skip_typmods = false;
+
+ if (type_name->setof)
+ deparseAppendStringInfoString(state, "SETOF ");
+
+ if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
+ {
+ const char *name = strVal(lsecond(type_name->names));
+ if (strcmp(name, "bpchar") == 0)
+ {
+ deparseAppendStringInfoString(state, "char");
+ }
+ else if (strcmp(name, "varchar") == 0)
+ {
+ deparseAppendStringInfoString(state, "varchar");
+ }
+ else if (strcmp(name, "numeric") == 0)
+ {
+ deparseAppendStringInfoString(state, "numeric");
+ }
+ else if (strcmp(name, "bool") == 0)
+ {
+ deparseAppendStringInfoString(state, "boolean");
+ }
+ else if (strcmp(name, "int2") == 0)
+ {
+ deparseAppendStringInfoString(state, "smallint");
+ }
+ else if (strcmp(name, "int4") == 0)
+ {
+ deparseAppendStringInfoString(state, "int");
+ }
+ else if (strcmp(name, "int8") == 0)
+ {
+ deparseAppendStringInfoString(state, "bigint");
+ }
+ else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
+ {
+ deparseAppendStringInfoString(state, "real");
+ }
+ else if (strcmp(name, "float8") == 0)
+ {
+ deparseAppendStringInfoString(state, "double precision");
+ }
+ else if (strcmp(name, "time") == 0)
+ {
+ deparseAppendStringInfoString(state, "time");
+ }
+ else if (strcmp(name, "timetz") == 0)
+ {
+ deparseAppendStringInfoString(state, "time ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(state, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ deparseAppendStringInfoString(state, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "timestamp") == 0)
+ {
+ deparseAppendStringInfoString(state, "timestamp");
+ }
+ else if (strcmp(name, "timestamptz") == 0)
+ {
+ deparseAppendStringInfoString(state, "timestamp ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(state, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ deparseAppendStringInfoString(state, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
+ {
+ deparseAppendStringInfoString(state, "interval");
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
+ {
+ deparseAppendStringInfoString(state, "interval");
+ deparseIntervalTypmods(state, type_name);
+
+ skip_typmods = true;
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "pg_catalog.");
+ deparseAppendStringInfoString(state, name);
+ }
+ }
+ else
+ {
+ deparseAnyName(state, type_name->names);
+ }
+
+ if (list_length(type_name->typmods) > 0 && !skip_typmods)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, type_name->typmods)
+ {
+ if (IsA(lfirst(lc), A_Const))
+ deparseAConst(state, lfirst(lc));
+ else if (IsA(lfirst(lc), ParamRef))
+ deparseParamRef(state, lfirst(lc));
+ else if (IsA(lfirst(lc), ColumnRef))
+ deparseColumnRef(state, lfirst(lc));
+ else
+ Assert(false);
+
+ if (lnext(type_name->typmods, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ foreach(lc, type_name->arrayBounds)
+ {
+ deparseAppendStringInfoChar(state, '[');
+ if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
+ deparseSignedIconst(state, lfirst(lc));
+ deparseAppendStringInfoChar(state, ']');
+ }
+
+ if (type_name->pct_type)
+ deparseAppendStringInfoString(state, "%type");
+}
+
+// Handle typemods for Interval types separately
+// so that they can be applied appropriately for different contexts.
+// For example, when using `SET` a query like `INTERVAL 'x' hour TO minute`
+// the `INTERVAL` keyword is specified first.
+// In all other contexts, intervals use the `'x'::interval` style.
+static void deparseIntervalTypmods(DeparseState *state, TypeName *type_name)
+{
+ const char *name = strVal(lsecond(type_name->names));
+ Assert(strcmp(name, "interval") == 0);
+ Assert(list_length(type_name->typmods) >= 1);
+ Assert(IsA(linitial(type_name->typmods), A_Const));
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
+
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
+
+ // This logic is based on intervaltypmodout in timestamp.c
+ switch (fields)
+ {
+ case INTERVAL_MASK(YEAR):
+ deparseAppendStringInfoString(state, " year");
+ break;
+ case INTERVAL_MASK(MONTH):
+ deparseAppendStringInfoString(state, " month");
+ break;
+ case INTERVAL_MASK(DAY):
+ deparseAppendStringInfoString(state, " day");
+ break;
+ case INTERVAL_MASK(HOUR):
+ deparseAppendStringInfoString(state, " hour");
+ break;
+ case INTERVAL_MASK(MINUTE):
+ deparseAppendStringInfoString(state, " minute");
+ break;
+ case INTERVAL_MASK(SECOND):
+ deparseAppendStringInfoString(state, " second");
+ break;
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+ deparseAppendStringInfoString(state, " year to month");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+ deparseAppendStringInfoString(state, " day to hour");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ deparseAppendStringInfoString(state, " day to minute");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ deparseAppendStringInfoString(state, " day to second");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ deparseAppendStringInfoString(state, " hour to minute");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ deparseAppendStringInfoString(state, " hour to second");
+ break;
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ deparseAppendStringInfoString(state, " minute to second");
+ break;
+ case INTERVAL_FULL_RANGE:
+ // Nothing
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (list_length(type_name->typmods) == 2)
+ {
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
+ if (precision != INTERVAL_FULL_PRECISION)
+ deparseAppendStringInfo(state, "(%d)", precision);
+ }
+}
+
+static void deparseNullTest(DeparseState *state, NullTest *null_test)
+{
+ // argisrow is always false in raw parser output
+ Assert(null_test->argisrow == false);
+
+ deparseExpr(state, (Node *) null_test->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ switch (null_test->nulltesttype)
+ {
+ case IS_NULL:
+ deparseAppendStringInfoString(state, " IS NULL");
+ break;
+ case IS_NOT_NULL:
+ deparseAppendStringInfoString(state, " IS NOT NULL");
+ break;
+ }
+}
+
+// "case_expr" in gram.y
+static void deparseCaseExpr(DeparseState *state, CaseExpr *case_expr)
+{
+ ListCell *lc;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ deparseAppendStringInfoString(state, "CASE ");
+
+ if (case_expr->arg != NULL)
+ {
+ deparseExpr(state, (Node *) case_expr->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ parent_level = deparseStateIncreaseNestingLevel(state);
+
+ foreach(lc, case_expr->args)
+ {
+ deparseCaseWhen(state, castNode(CaseWhen, lfirst(lc)));
+ }
+
+ if (case_expr->defresult != NULL)
+ {
+ deparseAppendPartGroup(state, "ELSE", DEPARSE_PART_INDENT);
+ deparseExpr(state, (Node *) case_expr->defresult, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStateDecreaseNestingLevel(state, parent_level);
+
+ deparseAppendStringInfoString(state, "END");
+}
+
+// "when_clause" in gram.y
+static void deparseCaseWhen(DeparseState *state, CaseWhen *case_when)
+{
+ deparseAppendPartGroup(state, "WHEN", DEPARSE_PART_INDENT);
+ deparseExpr(state, (Node *) case_when->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " THEN ");
+ deparseExpr(state, (Node *) case_when->result, DEPARSE_NODE_CONTEXT_A_EXPR);
+}
+
+static void deparseAIndirection(DeparseState *state, A_Indirection *a_indirection)
+{
+ ListCell *lc;
+ bool need_parens =
+ IsA(a_indirection->arg, A_Indirection) ||
+ IsA(a_indirection->arg, FuncCall) ||
+ IsA(a_indirection->arg, A_Expr) ||
+ IsA(a_indirection->arg, TypeCast) ||
+ IsA(a_indirection->arg, RowExpr) ||
+ (IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices)) ||
+ IsA(a_indirection->arg, JsonFuncExpr);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseExpr(state, a_indirection->arg, need_parens ? DEPARSE_NODE_CONTEXT_A_EXPR : DEPARSE_NODE_CONTEXT_NONE);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ deparseOptIndirection(state, a_indirection->indirection, 0);
+}
+
+static void deparseAIndices(DeparseState *state, A_Indices *a_indices)
+{
+ deparseAppendStringInfoChar(state, '[');
+ if (a_indices->lidx != NULL)
+ deparseExpr(state, a_indices->lidx, DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (a_indices->is_slice)
+ deparseAppendStringInfoChar(state, ':');
+ if (a_indices->uidx != NULL)
+ deparseExpr(state, a_indices->uidx, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ']');
+}
+
+static void deparseCoalesceExpr(DeparseState *state, CoalesceExpr *coalesce_expr)
+{
+ deparseAppendStringInfoString(state, "COALESCE(");
+ deparseExprList(state, coalesce_expr->args);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseMinMaxExpr(DeparseState *state, MinMaxExpr *min_max_expr)
+{
+ switch (min_max_expr->op)
+ {
+ case IS_GREATEST:
+ deparseAppendStringInfoString(state, "GREATEST(");
+ break;
+ case IS_LEAST:
+ deparseAppendStringInfoString(state, "LEAST(");
+ break;
+ }
+ deparseExprList(state, min_max_expr->args);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseBooleanTest(DeparseState *state, BooleanTest *boolean_test)
+{
+ bool need_parens = IsA(boolean_test->arg, BoolExpr);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseExpr(state, (Node *) boolean_test->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ switch (boolean_test->booltesttype)
+ {
+ case IS_TRUE:
+ deparseAppendStringInfoString(state, " IS TRUE");
+ break;
+ case IS_NOT_TRUE:
+ deparseAppendStringInfoString(state, " IS NOT TRUE");
+ break;
+ case IS_FALSE:
+ deparseAppendStringInfoString(state, " IS FALSE");
+ break;
+ case IS_NOT_FALSE:
+ deparseAppendStringInfoString(state, " IS NOT FALSE");
+ break;
+ case IS_UNKNOWN:
+ deparseAppendStringInfoString(state, " IS UNKNOWN");
+ break;
+ case IS_NOT_UNKNOWN:
+ deparseAppendStringInfoString(state, " IS NOT UNKNOWN");
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "columnDef" and "alter_table_cmd" in gram.y
+static void deparseColumnDef(DeparseState *state, ColumnDef *column_def)
+{
+ ListCell *lc;
+
+ if (column_def->colname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(column_def->colname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->typeName != NULL)
+ {
+ deparseTypeName(state, column_def->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->storage_name)
+ {
+ deparseAppendStringInfoString(state, "STORAGE ");
+ deparseAppendStringInfoString(state, column_def->storage_name);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->raw_default != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseExpr(state, column_def->raw_default, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->compression != NULL)
+ {
+ deparseAppendStringInfoString(state, "COMPRESSION ");
+ deparseAppendStringInfoString(state, column_def->compression);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->fdwoptions != NULL)
+ {
+ deparseCreateGenericOptions(state, column_def->fdwoptions);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ foreach(lc, column_def->constraints)
+ {
+ deparseConstraint(state, castNode(Constraint, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->collClause != NULL)
+ {
+ deparseCollateClause(state, column_def->collClause);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseInsertOverride(DeparseState *state, OverridingKind override)
+{
+ switch (override)
+ {
+ case OVERRIDING_NOT_SET:
+ // Do nothing
+ break;
+ case OVERRIDING_USER_VALUE:
+ deparseAppendStringInfoString(state, "OVERRIDING USER VALUE ");
+ break;
+ case OVERRIDING_SYSTEM_VALUE:
+ deparseAppendStringInfoString(state, "OVERRIDING SYSTEM VALUE ");
+ break;
+ }
+}
+
+static void deparseInsertStmt(DeparseState *state, InsertStmt *insert_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ DeparseStateNestingLevel *parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (insert_stmt->withClause != NULL)
+ {
+ deparseWithClause(state, insert_stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "INSERT INTO", DEPARSE_PART_INDENT);
+ deparseRangeVar(state, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(insert_stmt->cols) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseInsertColumnList(state, insert_stmt->cols);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseInsertOverride(state, insert_stmt->override);
+
+ if (insert_stmt->selectStmt != NULL)
+ {
+ deparseSelectStmt(state, castNode(SelectStmt, insert_stmt->selectStmt), DEPARSE_NODE_CONTEXT_INSERT_SELECT);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "DEFAULT VALUES ");
+ }
+
+ if (insert_stmt->onConflictClause != NULL)
+ {
+ deparseOnConflictClause(state, insert_stmt->onConflictClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(insert_stmt->returningList) > 0)
+ {
+ deparseAppendPartGroup(state, "RETURNING", DEPARSE_PART_INDENT_AND_MERGE);
+ deparseTargetList(state, insert_stmt->returningList);
+ }
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+static void deparseInferClause(DeparseState *state, InferClause *infer_clause)
+{
+ ListCell *lc;
+
+ if (list_length(infer_clause->indexElems) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, infer_clause->indexElems)
+ {
+ deparseIndexElem(state, lfirst(lc));
+ if (lnext(infer_clause->indexElems, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (infer_clause->conname != NULL)
+ {
+ deparseAppendStringInfoString(state, "ON CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(infer_clause->conname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseWhereClause(state, infer_clause->whereClause);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseOnConflictClause(DeparseState *state, OnConflictClause *on_conflict_clause)
+{
+ ListCell *lc;
+
+ deparseAppendPartGroup(state, "ON CONFLICT", DEPARSE_PART_INDENT);
+
+ if (on_conflict_clause->infer != NULL)
+ {
+ deparseInferClause(state, on_conflict_clause->infer);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (on_conflict_clause->action)
+ {
+ case ONCONFLICT_NONE:
+ Assert(false);
+ break;
+ case ONCONFLICT_NOTHING:
+ deparseAppendStringInfoString(state, "DO NOTHING ");
+ break;
+ case ONCONFLICT_UPDATE:
+ deparseAppendStringInfoString(state, "DO UPDATE ");
+ break;
+ }
+
+ if (list_length(on_conflict_clause->targetList) > 0)
+ {
+ deparseAppendPartGroup(state, "SET", DEPARSE_PART_INDENT);
+ deparseSetClauseList(state, on_conflict_clause->targetList);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseWhereClause(state, on_conflict_clause->whereClause);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseUpdateStmt(DeparseState *state, UpdateStmt *update_stmt)
+{
+ ListCell* lc;
+ ListCell* lc2;
+ ListCell* lc3;
+ DeparseStateNestingLevel *parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (update_stmt->withClause != NULL)
+ {
+ deparseWithClause(state, update_stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "UPDATE", DEPARSE_PART_INDENT);
+ deparseRangeVar(state, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(update_stmt->targetList) > 0)
+ {
+ deparseAppendPartGroup(state, "SET", DEPARSE_PART_INDENT);
+ deparseSetClauseList(state, update_stmt->targetList);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseFromClause(state, update_stmt->fromClause);
+ deparseWhereOrCurrentClause(state, update_stmt->whereClause);
+
+ if (list_length(update_stmt->returningList) > 0)
+ {
+ deparseAppendPartGroup(state, "RETURNING", DEPARSE_PART_INDENT_AND_MERGE);
+ deparseTargetList(state, update_stmt->returningList);
+ }
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+// "MergeStmt" in gram.y
+static void deparseMergeStmt(DeparseState *state, MergeStmt *merge_stmt)
+{
+ DeparseStateNestingLevel *parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (merge_stmt->withClause != NULL)
+ {
+ deparseWithClause(state, merge_stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "MERGE", DEPARSE_PART_INDENT);
+ deparseAppendStringInfoString(state, "INTO ");
+ deparseRangeVar(state, merge_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendPartGroup(state, "USING", DEPARSE_PART_INDENT);
+ deparseTableRef(state, merge_stmt->sourceRelation);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "ON ");
+ deparseExpr(state, merge_stmt->joinCondition, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+
+ ListCell *lc;
+ foreach (lc, merge_stmt->mergeWhenClauses)
+ {
+ MergeWhenClause *clause = castNode(MergeWhenClause, lfirst(lc));
+
+ deparseAppendStringInfoString(state, "WHEN ");
+
+ switch (clause->matchKind)
+ {
+ case MERGE_WHEN_MATCHED:
+ deparseAppendStringInfoString(state, "MATCHED ");
+ break;
+ case MERGE_WHEN_NOT_MATCHED_BY_SOURCE:
+ deparseAppendStringInfoString(state, "NOT MATCHED BY SOURCE ");
+ break;
+ case MERGE_WHEN_NOT_MATCHED_BY_TARGET:
+ deparseAppendStringInfoString(state, "NOT MATCHED ");
+ break;
+ }
+
+ if (clause->condition)
+ {
+ deparseAppendStringInfoString(state, "AND ");
+ deparseExpr(state, clause->condition, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "THEN ");
+
+ switch (clause->commandType) {
+ case CMD_INSERT:
+ deparseAppendStringInfoString(state, "INSERT ");
+
+ if (clause->targetList) {
+ deparseAppendStringInfoChar(state, '(');
+ deparseInsertColumnList(state, clause->targetList);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseInsertOverride(state, clause->override);
+
+ if (clause->values) {
+ deparseAppendStringInfoString(state, "VALUES (");
+ deparseExprList(state, clause->values);
+ deparseAppendStringInfoString(state, ")");
+ } else {
+ deparseAppendStringInfoString(state, "DEFAULT VALUES ");
+ }
+
+ break;
+ case CMD_UPDATE:
+ deparseAppendStringInfoString(state, "UPDATE SET ");
+ deparseSetClauseList(state, clause->targetList);
+ break;
+ case CMD_DELETE:
+ deparseAppendStringInfoString(state, "DELETE");
+ break;
+ case CMD_NOTHING:
+ deparseAppendStringInfoString(state, "DO NOTHING");
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted command type in merge statement: %d", clause->commandType);
+ break;
+ }
+
+ if (lfirst(lc) != llast(merge_stmt->mergeWhenClauses))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (merge_stmt->returningList)
+ {
+ deparseAppendPartGroup(state, "RETURNING", DEPARSE_PART_INDENT_AND_MERGE);
+ deparseTargetList(state, merge_stmt->returningList);
+ }
+
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+static void deparseDeleteStmt(DeparseState *state, DeleteStmt *delete_stmt)
+{
+ DeparseStateNestingLevel *parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (delete_stmt->withClause != NULL)
+ {
+ deparseWithClause(state, delete_stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "DELETE", DEPARSE_PART_INDENT);
+ deparseAppendStringInfoString(state, "FROM ");
+ deparseRangeVar(state, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (delete_stmt->usingClause != NULL)
+ {
+ deparseAppendPartGroup(state, "USING", DEPARSE_PART_INDENT);
+ deparseFromList(state, delete_stmt->usingClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseWhereOrCurrentClause(state, delete_stmt->whereClause);
+
+ if (list_length(delete_stmt->returningList) > 0)
+ {
+ deparseAppendPartGroup(state, "RETURNING", DEPARSE_PART_INDENT_AND_MERGE);
+ deparseTargetList(state, delete_stmt->returningList);
+ }
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+static void deparseLockingClause(DeparseState *state, LockingClause *locking_clause)
+{
+ ListCell *lc;
+
+ switch (locking_clause->strength)
+ {
+ case LCS_NONE:
+ /* no such clause - only used in PlanRowMark */
+ Assert(false);
+ break;
+ case LCS_FORKEYSHARE:
+ deparseAppendPartGroup(state, "FOR KEY SHARE", DEPARSE_PART_INDENT);
+ break;
+ case LCS_FORSHARE:
+ deparseAppendPartGroup(state, "FOR SHARE", DEPARSE_PART_INDENT);
+ break;
+ case LCS_FORNOKEYUPDATE:
+ deparseAppendPartGroup(state, "FOR NO KEY UPDATE", DEPARSE_PART_INDENT);
+ break;
+ case LCS_FORUPDATE:
+ deparseAppendPartGroup(state, "FOR UPDATE", DEPARSE_PART_INDENT);
+ break;
+ }
+
+ if (list_length(locking_clause->lockedRels) > 0)
+ {
+ deparseAppendStringInfoString(state, "OF ");
+ deparseQualifiedNameList(state, locking_clause->lockedRels);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (locking_clause->waitPolicy)
+ {
+ case LockWaitError:
+ deparseAppendStringInfoString(state, "NOWAIT");
+ break;
+ case LockWaitSkip:
+ deparseAppendStringInfoString(state, "SKIP LOCKED");
+ break;
+ case LockWaitBlock:
+ // Default
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseSetToDefault(DeparseState *state, SetToDefault *set_to_default)
+{
+ deparseAppendStringInfoString(state, "DEFAULT");
+}
+
+static void deparseCreateCastStmt(DeparseState *state, CreateCastStmt *create_cast_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ deparseAppendStringInfoString(state, "CREATE CAST (");
+ deparseTypeName(state, create_cast_stmt->sourcetype);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, create_cast_stmt->targettype);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (create_cast_stmt->func != NULL)
+ {
+ deparseAppendStringInfoString(state, "WITH FUNCTION ");
+ deparseFunctionWithArgtypes(state, create_cast_stmt->func);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (create_cast_stmt->inout)
+ {
+ deparseAppendStringInfoString(state, "WITH INOUT ");
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "WITHOUT FUNCTION ");
+ }
+
+ switch (create_cast_stmt->context)
+ {
+ case COERCION_IMPLICIT:
+ deparseAppendStringInfoString(state, "AS IMPLICIT");
+ break;
+ case COERCION_ASSIGNMENT:
+ deparseAppendStringInfoString(state, "AS ASSIGNMENT");
+ break;
+ case COERCION_PLPGSQL:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCION_EXPLICIT:
+ // Default
+ break;
+ }
+}
+
+static void deparseCreateOpClassStmt(DeparseState *state, CreateOpClassStmt *create_op_class_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE OPERATOR CLASS ");
+
+ deparseAnyName(state, create_op_class_stmt->opclassname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_op_class_stmt->isDefault)
+ deparseAppendStringInfoString(state, "DEFAULT ");
+
+ deparseAppendStringInfoString(state, "FOR TYPE ");
+ deparseTypeName(state, create_op_class_stmt->datatype);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(create_op_class_stmt->amname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_op_class_stmt->opfamilyname != NULL)
+ {
+ deparseAppendStringInfoString(state, "FAMILY ");
+ deparseAnyName(state, create_op_class_stmt->opfamilyname);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "AS ");
+ deparseOpclassItemList(state, create_op_class_stmt->items);
+}
+
+static void deparseCreateOpFamilyStmt(DeparseState *state, CreateOpFamilyStmt *create_op_family_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE OPERATOR FAMILY ");
+
+ deparseAnyName(state, create_op_family_stmt->opfamilyname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(create_op_family_stmt->amname));
+}
+
+static void deparseCreateOpClassItem(DeparseState *state, CreateOpClassItem *create_op_class_item)
+{
+ ListCell *lc = NULL;
+
+ switch (create_op_class_item->itemtype)
+ {
+ case OPCLASS_ITEM_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ deparseAppendStringInfo(state, "%d ", create_op_class_item->number);
+
+ if (create_op_class_item->name != NULL)
+ {
+ if (create_op_class_item->name->objargs != NULL)
+ deparseOperatorWithArgtypes(state, create_op_class_item->name);
+ else
+ deparseAnyOperator(state, create_op_class_item->name->objname);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_op_class_item->order_family != NULL)
+ {
+ deparseAppendStringInfoString(state, "FOR ORDER BY ");
+ deparseAnyName(state, create_op_class_item->order_family);
+ }
+
+ if (create_op_class_item->class_args != NULL)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeList(state, create_op_class_item->class_args);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ removeTrailingSpace(state);
+ break;
+ case OPCLASS_ITEM_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseAppendStringInfo(state, "%d ", create_op_class_item->number);
+ if (create_op_class_item->class_args != NULL)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeList(state, create_op_class_item->class_args);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ if (create_op_class_item->name != NULL)
+ deparseFunctionWithArgtypes(state, create_op_class_item->name);
+ removeTrailingSpace(state);
+ break;
+ case OPCLASS_ITEM_STORAGETYPE:
+ deparseAppendStringInfoString(state, "STORAGE ");
+ deparseTypeName(state, create_op_class_item->storedtype);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseTableLikeClause(DeparseState *state, TableLikeClause *table_like_clause)
+{
+ deparseAppendStringInfoString(state, "LIKE ");
+ deparseRangeVar(state, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
+ deparseAppendStringInfoString(state, "INCLUDING ALL ");
+ else
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+ deparseAppendStringInfoString(state, "INCLUDING COMMENTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION)
+ deparseAppendStringInfoString(state, "INCLUDING COMPRESSION ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ deparseAppendStringInfoString(state, "INCLUDING CONSTRAINTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
+ deparseAppendStringInfoString(state, "INCLUDING DEFAULTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
+ deparseAppendStringInfoString(state, "INCLUDING IDENTITY ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED)
+ deparseAppendStringInfoString(state, "INCLUDING GENERATED ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ deparseAppendStringInfoString(state, "INCLUDING INDEXES ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
+ deparseAppendStringInfoString(state, "INCLUDING STATISTICS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ deparseAppendStringInfoString(state, "INCLUDING STORAGE ");
+ }
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateDomainStmt(DeparseState *state, CreateDomainStmt *create_domain_stmt)
+{
+ ListCell *lc;
+
+ Assert(create_domain_stmt->typeName != NULL);
+
+ deparseAppendStringInfoString(state, "CREATE DOMAIN ");
+ deparseAnyName(state, create_domain_stmt->domainname);
+ deparseAppendStringInfoString(state, " AS ");
+
+ deparseTypeName(state, create_domain_stmt->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_domain_stmt->collClause != NULL)
+ {
+ deparseCollateClause(state, create_domain_stmt->collClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ foreach(lc, create_domain_stmt->constraints)
+ {
+ deparseConstraint(state, castNode(Constraint, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateExtensionStmt(DeparseState *state, CreateExtensionStmt *create_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE EXTENSION ");
+
+ if (create_extension_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseColId(state, create_extension_stmt->extname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ foreach (lc, create_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "schema") == 0)
+ {
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ deparseColId(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ deparseAppendStringInfoString(state, "VERSION ");
+ deparseNonReservedWordOrSconst(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "cascade") == 0)
+ {
+ deparseAppendStringInfoString(state, "CASCADE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "ColConstraintElem" and "ConstraintElem" in gram.y
+static void deparseConstraint(DeparseState *state, Constraint *constraint)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(constraint->conname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (constraint->contype) {
+ case CONSTR_NULL:
+ deparseAppendStringInfoString(state, "NULL ");
+ break;
+ case CONSTR_NOTNULL:
+ deparseAppendStringInfoString(state, "NOT NULL ");
+ break;
+ case CONSTR_DEFAULT:
+ deparseAppendStringInfoString(state, "DEFAULT ");
+ deparseBExpr(state, constraint->raw_expr);
+ break;
+ case CONSTR_IDENTITY:
+ deparseAppendStringInfoString(state, "GENERATED ");
+ switch (constraint->generated_when)
+ {
+ case ATTRIBUTE_IDENTITY_ALWAYS:
+ deparseAppendStringInfoString(state, "ALWAYS ");
+ break;
+ case ATTRIBUTE_IDENTITY_BY_DEFAULT:
+ deparseAppendStringInfoString(state, "BY DEFAULT ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseAppendStringInfoString(state, "AS IDENTITY ");
+ deparseOptParenthesizedSeqOptList(state, constraint->options);
+ break;
+ case CONSTR_GENERATED:
+ Assert(constraint->generated_when == ATTRIBUTE_IDENTITY_ALWAYS);
+ deparseAppendStringInfoString(state, "GENERATED ALWAYS AS (");
+ deparseExpr(state, constraint->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") STORED ");
+ break;
+ case CONSTR_CHECK:
+ deparseAppendStringInfoString(state, "CHECK (");
+ deparseExpr(state, constraint->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ break;
+ case CONSTR_PRIMARY:
+ deparseAppendStringInfoString(state, "PRIMARY KEY ");
+ break;
+ case CONSTR_UNIQUE:
+ deparseAppendStringInfoString(state, "UNIQUE ");
+ if (constraint->nulls_not_distinct)
+ deparseAppendStringInfoString(state, "NULLS NOT DISTINCT ");
+ break;
+ case CONSTR_EXCLUSION:
+ deparseAppendStringInfoString(state, "EXCLUDE ");
+ if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(constraint->access_method));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, constraint->exclusions)
+ {
+ List *exclusion = castNode(List, lfirst(lc));
+ Assert(list_length(exclusion) == 2);
+ deparseIndexElem(state, castNode(IndexElem, linitial(exclusion)));
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyOperator(state, castNode(List, lsecond(exclusion)));
+ if (lnext(constraint->exclusions, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ if (constraint->where_clause != NULL)
+ {
+ deparseAppendStringInfoString(state, "WHERE (");
+ deparseExpr(state, constraint->where_clause, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ break;
+ case CONSTR_FOREIGN:
+ if (list_length(constraint->fk_attrs) > 0)
+ deparseAppendStringInfoString(state, "FOREIGN KEY ");
+ break;
+ case CONSTR_ATTR_DEFERRABLE:
+ deparseAppendStringInfoString(state, "DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ deparseAppendStringInfoString(state, "NOT DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_DEFERRED:
+ deparseAppendStringInfoString(state, "INITIALLY DEFERRED ");
+ break;
+ case CONSTR_ATTR_IMMEDIATE:
+ deparseAppendStringInfoString(state, "INITIALLY IMMEDIATE ");
+ break;
+ }
+
+ if (list_length(constraint->keys) > 0)
+ {
+ bool valueOnly = false;
+
+ if (list_length(constraint->keys) == 1) {
+ Node* firstKey = constraint->keys->elements[0].ptr_value;
+ valueOnly = IsA(firstKey, String) && !strcmp("value", ((String*)firstKey)->sval);
+ }
+
+ if (!valueOnly) {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, constraint->keys);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ }
+
+ if (list_length(constraint->fk_attrs) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, constraint->fk_attrs);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (constraint->pktable != NULL)
+ {
+ deparseAppendStringInfoString(state, "REFERENCES ");
+ deparseRangeVar(state, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ if (list_length(constraint->pk_attrs) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, constraint->pk_attrs);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ }
+
+ switch (constraint->fk_matchtype)
+ {
+ case FKCONSTR_MATCH_SIMPLE:
+ // Default
+ break;
+ case FKCONSTR_MATCH_FULL:
+ deparseAppendStringInfoString(state, "MATCH FULL ");
+ break;
+ case FKCONSTR_MATCH_PARTIAL:
+ // Not implemented in Postgres
+ Assert(false);
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_upd_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ deparseAppendStringInfoString(state, "ON UPDATE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ deparseAppendStringInfoString(state, "ON UPDATE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ deparseAppendStringInfoString(state, "ON UPDATE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ deparseAppendStringInfoString(state, "ON UPDATE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_del_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ deparseAppendStringInfoString(state, "ON DELETE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ deparseAppendStringInfoString(state, "ON DELETE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ case FKCONSTR_ACTION_SETDEFAULT:
+ deparseAppendStringInfoString(state, "ON DELETE SET ");
+
+ switch (constraint->fk_del_action) {
+ case FKCONSTR_ACTION_SETDEFAULT: deparseAppendStringInfoString(state, "DEFAULT "); break;
+ case FKCONSTR_ACTION_SETNULL: deparseAppendStringInfoString(state, "NULL "); break;
+ }
+
+ if (constraint->fk_del_set_cols) {
+ deparseAppendStringInfoString(state, "(");
+ ListCell *lc;
+ foreach (lc, constraint->fk_del_set_cols) {
+ deparseAppendStringInfoString(state, strVal(lfirst(lc)));
+ if (lfirst(lc) != llast(constraint->fk_del_set_cols))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ")");
+ }
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ if (list_length(constraint->including) > 0)
+ {
+ deparseAppendStringInfoString(state, "INCLUDE (");
+ deparseColumnList(state, constraint->including);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ switch (constraint->contype)
+ {
+ case CONSTR_PRIMARY:
+ case CONSTR_UNIQUE:
+ case CONSTR_EXCLUSION:
+ deparseOptWith(state, constraint->options);
+ break;
+ default:
+ break;
+ }
+
+ if (constraint->indexname != NULL)
+ deparseAppendStringInfo(state, "USING INDEX %s ", quote_identifier(constraint->indexname));
+
+ if (constraint->indexspace != NULL)
+ deparseAppendStringInfo(state, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
+
+ if (constraint->deferrable)
+ deparseAppendStringInfoString(state, "DEFERRABLE ");
+
+ if (constraint->initdeferred)
+ deparseAppendStringInfoString(state, "INITIALLY DEFERRED ");
+
+ if (constraint->is_no_inherit)
+ deparseAppendStringInfoString(state, "NO INHERIT ");
+
+ if (constraint->skip_validation)
+ deparseAppendStringInfoString(state, "NOT VALID ");
+
+ removeTrailingSpace(state);
+}
+
+// "ReturnStmt" in gram.y
+static void deparseReturnStmt(DeparseState *state, ReturnStmt *return_stmt)
+{
+ deparseAppendStringInfoString(state, "RETURN ");
+ deparseExpr(state, return_stmt->returnval, DEPARSE_NODE_CONTEXT_A_EXPR);
+}
+
+static void deparseCreateFunctionStmt(DeparseState *state, CreateFunctionStmt *create_function_stmt)
+{
+ ListCell *lc;
+ bool tableFunc = false;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+ if (create_function_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+ if (create_function_stmt->is_procedure)
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ else
+ deparseAppendStringInfoString(state, "FUNCTION ");
+
+ deparseFuncName(state, create_function_stmt->funcname);
+
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode != FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(state, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc) && castNode(FunctionParameter, lfirst(lnext(create_function_stmt->parameters, lc)))->mode != FUNC_PARAM_TABLE)
+ deparseAppendStringInfoString(state, ", ");
+ }
+ else
+ {
+ tableFunc = true;
+ }
+ }
+ deparseAppendStringInfoString(state, ") ");
+
+ if (tableFunc)
+ {
+ deparseAppendStringInfoString(state, "RETURNS TABLE (");
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode == FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(state, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ else if (create_function_stmt->returnType != NULL)
+ {
+ deparseAppendStringInfoString(state, "RETURNS ");
+ deparseTypeName(state, create_function_stmt->returnType);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ foreach(lc, create_function_stmt->options)
+ {
+ deparseCreateFuncOptItem(state, castNode(DefElem, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_function_stmt->sql_body)
+ {
+ /* RETURN or BEGIN ... END
+ */
+ if (IsA(create_function_stmt->sql_body, ReturnStmt))
+ {
+ deparseReturnStmt(state, castNode(ReturnStmt, create_function_stmt->sql_body));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "BEGIN ATOMIC ");
+ if (IsA(create_function_stmt->sql_body, List), linitial((List *) create_function_stmt->sql_body) != NULL)
+ {
+ List *body_stmt_list = castNode(List, linitial((List *) create_function_stmt->sql_body));
+ foreach(lc, body_stmt_list)
+ {
+ if (IsA(lfirst(lc), ReturnStmt))
+ {
+ deparseReturnStmt(state, lfirst_node(ReturnStmt, lc));
+ deparseAppendStringInfoString(state, "; ");
+ }
+ else
+ {
+ deparseStmt(state, lfirst(lc));
+ deparseAppendStringInfoString(state, "; ");
+ }
+ }
+ }
+
+ deparseAppendStringInfoString(state, "END ");
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "func_arg", "func_arg_with_default" and other places in gram.y
+static void deparseFunctionParameter(DeparseState *state, FunctionParameter *function_parameter)
+{
+ switch (function_parameter->mode)
+ {
+ case FUNC_PARAM_IN: /* input only */
+ deparseAppendStringInfoString(state, "IN ");
+ break;
+ case FUNC_PARAM_OUT: /* output only */
+ deparseAppendStringInfoString(state, "OUT ");
+ break;
+ case FUNC_PARAM_INOUT: /* both */
+ deparseAppendStringInfoString(state, "INOUT ");
+ break;
+ case FUNC_PARAM_VARIADIC: /* variadic (always input) */
+ deparseAppendStringInfoString(state, "VARIADIC ");
+ break;
+ case FUNC_PARAM_TABLE: /* table function output column */
+ // No special annotation, the caller is expected to correctly put
+ // this into the RETURNS part of the CREATE FUNCTION statement
+ break;
+ case FUNC_PARAM_DEFAULT:
+ // Default
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (function_parameter->name != NULL)
+ {
+ deparseAppendStringInfoString(state, function_parameter->name);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseTypeName(state, function_parameter->argType);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (function_parameter->defexpr != NULL)
+ {
+ deparseAppendStringInfoString(state, "= ");
+ deparseExpr(state, function_parameter->defexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCheckPointStmt(DeparseState *state, CheckPointStmt *check_point_stmt)
+{
+ deparseAppendStringInfoString(state, "CHECKPOINT");
+}
+
+static void deparseCreateSchemaStmt(DeparseState *state, CreateSchemaStmt *create_schema_stmt)
+{
+ ListCell *lc;
+ deparseAppendStringInfoString(state, "CREATE SCHEMA ");
+
+ if (create_schema_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ if (create_schema_stmt->schemaname)
+ {
+ deparseColId(state, create_schema_stmt->schemaname);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_schema_stmt->authrole != NULL)
+ {
+ deparseAppendStringInfoString(state, "AUTHORIZATION ");
+ deparseRoleSpec(state, create_schema_stmt->authrole);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_schema_stmt->schemaElts)
+ {
+ foreach(lc, create_schema_stmt->schemaElts)
+ {
+ deparseSchemaStmt(state, lfirst(lc));
+ if (lnext(create_schema_stmt->schemaElts, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterRoleSetStmt(DeparseState *state, AlterRoleSetStmt *alter_role_set_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER ROLE ");
+
+ if (alter_role_set_stmt->role == NULL)
+ deparseAppendStringInfoString(state, "ALL");
+ else
+ deparseRoleSpec(state, alter_role_set_stmt->role);
+
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_role_set_stmt->database != NULL)
+ {
+ deparseAppendStringInfoString(state, "IN DATABASE ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_role_set_stmt->database));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseVariableSetStmt(state, alter_role_set_stmt->setstmt);
+}
+
+static void deparseCreateConversionStmt(DeparseState *state, CreateConversionStmt *create_conversion_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE ");
+ if (create_conversion_stmt->def)
+ deparseAppendStringInfoString(state, "DEFAULT ");
+
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ deparseAnyName(state, create_conversion_stmt->conversion_name);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseStringLiteral(state, create_conversion_stmt->for_encoding_name);
+ deparseAppendStringInfoString(state, " TO ");
+ deparseStringLiteral(state, create_conversion_stmt->to_encoding_name);
+
+ deparseAppendStringInfoString(state, "FROM ");
+ deparseAnyName(state, create_conversion_stmt->func_name);
+}
+
+static void deparseRoleSpec(DeparseState *state, RoleSpec *role_spec)
+{
+ switch (role_spec->roletype)
+ {
+ case ROLESPEC_CSTRING:
+ Assert(role_spec->rolename != NULL);
+ deparseAppendStringInfoString(state, quote_identifier(role_spec->rolename));
+ break;
+ case ROLESPEC_CURRENT_ROLE:
+ deparseAppendStringInfoString(state, "CURRENT_ROLE");
+ break;
+ case ROLESPEC_CURRENT_USER:
+ deparseAppendStringInfoString(state, "CURRENT_USER");
+ break;
+ case ROLESPEC_SESSION_USER:
+ deparseAppendStringInfoString(state, "SESSION_USER");
+ break;
+ case ROLESPEC_PUBLIC:
+ deparseAppendStringInfoString(state, "public");
+ break;
+ }
+}
+
+// "part_elem" in gram.y
+static void deparsePartitionElem(DeparseState *state, PartitionElem *partition_elem)
+{
+ ListCell *lc;
+
+ if (partition_elem->name != NULL)
+ {
+ deparseColId(state, partition_elem->name);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (partition_elem->expr != NULL)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, partition_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseOptCollate(state, partition_elem->collation);
+ deparseAnyName(state, partition_elem->opclass);
+
+ removeTrailingSpace(state);
+}
+
+static void deparsePartitionSpec(DeparseState *state, PartitionSpec *partition_spec)
+{
+ ListCell *lc;
+
+ deparseAppendPartGroup(state, "PARTITION BY", DEPARSE_PART_INDENT);
+
+ switch (partition_spec->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ deparseAppendStringInfoString(state, "LIST");
+ break;
+ case PARTITION_STRATEGY_HASH:
+ deparseAppendStringInfoString(state, "HASH");
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ deparseAppendStringInfoString(state, "RANGE");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, " (");
+ foreach(lc, partition_spec->partParams)
+ {
+ deparsePartitionElem(state, castNode(PartitionElem, lfirst(lc)));
+ if (lnext(partition_spec->partParams, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparsePartitionBoundSpec(DeparseState *state, PartitionBoundSpec *partition_bound_spec)
+{
+ ListCell *lc;
+
+ if (partition_bound_spec->is_default)
+ {
+ deparseAppendStringInfoString(state, "DEFAULT");
+ return;
+ }
+
+ deparseAppendStringInfoString(state, "FOR VALUES ");
+
+ switch (partition_bound_spec->strategy)
+ {
+ case PARTITION_STRATEGY_HASH:
+ deparseAppendStringInfo(state, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
+ break;
+ case PARTITION_STRATEGY_LIST:
+ deparseAppendStringInfoString(state, "IN (");
+ deparseExprList(state, partition_bound_spec->listdatums);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ deparseAppendStringInfoString(state, "FROM (");
+ deparseExprList(state, partition_bound_spec->lowerdatums);
+ deparseAppendStringInfoString(state, ") TO (");
+ deparseExprList(state, partition_bound_spec->upperdatums);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparsePartitionCmd(DeparseState *state, PartitionCmd *partition_cmd)
+{
+ deparseRangeVar(state, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (partition_cmd->bound != NULL)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparsePartitionBoundSpec(state, partition_cmd->bound);
+ }
+ if (partition_cmd->concurrent)
+ deparseAppendStringInfoString(state, " CONCURRENTLY ");
+}
+
+// "TableElement" in gram.y
+static void deparseTableElement(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnDef:
+ deparseColumnDef(state, castNode(ColumnDef, node));
+ break;
+ case T_TableLikeClause:
+ deparseTableLikeClause(state, castNode(TableLikeClause, node));
+ break;
+ case T_Constraint:
+ deparseConstraint(state, castNode(Constraint, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseCreateStmt(DeparseState *state, CreateStmt *create_stmt, bool is_foreign_table)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (is_foreign_table)
+ deparseAppendStringInfoString(state, "FOREIGN ");
+
+ deparseOptTemp(state, create_stmt->relation->relpersistence);
+
+ deparseAppendStringInfoString(state, "TABLE ");
+
+ if (create_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseRangeVar(state, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_stmt->ofTypename != NULL)
+ {
+ deparseAppendStringInfoString(state, "OF ");
+ deparseTypeName(state, create_stmt->ofTypename);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ Assert(list_length(create_stmt->inhRelations) == 1);
+ deparseAppendStringInfoString(state, "PARTITION OF ");
+ deparseRangeVar(state, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(create_stmt->tableElts) > 0)
+ {
+ DeparseStateNestingLevel *parent_level = NULL;
+ // In raw parse output tableElts contains both columns and constraints
+ // (and the constraints field is NIL)
+ deparseAppendStringInfoChar(state, '(');
+ parent_level = deparseStateIncreaseNestingLevel(state);
+ foreach(lc, create_stmt->tableElts)
+ {
+ deparseTableElement(state, lfirst(lc));
+ if (lnext(create_stmt->tableElts, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
+ {
+ deparseAppendStringInfoString(state, "() ");
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ deparsePartitionBoundSpec(state, create_stmt->partbound);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ deparseOptInherit(state, create_stmt->inhRelations);
+ }
+
+ if (create_stmt->partspec != NULL)
+ {
+ deparsePartitionSpec(state, create_stmt->partspec);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_stmt->accessMethod != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(create_stmt->accessMethod));
+ }
+
+ deparseOptWith(state, create_stmt->options);
+
+ switch (create_stmt->oncommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No ON COMMIT clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ deparseAppendStringInfoString(state, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ deparseAppendStringInfoString(state, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ deparseAppendStringInfoString(state, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (create_stmt->tablespacename != NULL)
+ {
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseAppendStringInfoString(state, quote_identifier(create_stmt->tablespacename));
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateFdwStmt(DeparseState *state, CreateFdwStmt *create_fdw_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE FOREIGN DATA WRAPPER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_fdw_stmt->fdwname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(create_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(state, create_fdw_stmt->func_options);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseCreateGenericOptions(state, create_fdw_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterFdwStmt(DeparseState *state, AlterFdwStmt *alter_fdw_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER FOREIGN DATA WRAPPER ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_fdw_stmt->fdwname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(alter_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(state, alter_fdw_stmt->func_options);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(alter_fdw_stmt->options) > 0)
+ deparseAlterGenericOptions(state, alter_fdw_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateForeignServerStmt(DeparseState *state, CreateForeignServerStmt *create_foreign_server_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE SERVER ");
+ if (create_foreign_server_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+ deparseAppendStringInfoString(state, quote_identifier(create_foreign_server_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_foreign_server_stmt->servertype != NULL)
+ {
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseStringLiteral(state, create_foreign_server_stmt->servertype);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_foreign_server_stmt->version != NULL)
+ {
+ deparseAppendStringInfoString(state, "VERSION ");
+ deparseStringLiteral(state, create_foreign_server_stmt->version);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_foreign_server_stmt->fdwname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseCreateGenericOptions(state, create_foreign_server_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterForeignServerStmt(DeparseState *state, AlterForeignServerStmt *alter_foreign_server_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER SERVER ");
+
+ deparseAppendStringInfoString(state, quote_identifier(alter_foreign_server_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_foreign_server_stmt->has_version)
+ {
+ deparseAppendStringInfoString(state, "VERSION ");
+ if (alter_foreign_server_stmt->version != NULL)
+ deparseStringLiteral(state, alter_foreign_server_stmt->version);
+ else
+ deparseAppendStringInfoString(state, "NULL");
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(alter_foreign_server_stmt->options) > 0)
+ deparseAlterGenericOptions(state, alter_foreign_server_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateUserMappingStmt(DeparseState *state, CreateUserMappingStmt *create_user_mapping_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE USER MAPPING ");
+ if (create_user_mapping_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseRoleSpec(state, create_user_mapping_stmt->user);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_user_mapping_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseCreateGenericOptions(state, create_user_mapping_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreatedbStmt(DeparseState *state, CreatedbStmt *createdb_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE DATABASE ");
+ deparseColId(state, createdb_stmt->dbname);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseCreatedbOptList(state, createdb_stmt->options);
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterUserMappingStmt(DeparseState *state, AlterUserMappingStmt *alter_user_mapping_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER USER MAPPING FOR ");
+ deparseRoleSpec(state, alter_user_mapping_stmt->user);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_user_mapping_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAlterGenericOptions(state, alter_user_mapping_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDropUserMappingStmt(DeparseState *state, DropUserMappingStmt *drop_user_mapping_stmt)
+{
+ deparseAppendStringInfoString(state, "DROP USER MAPPING ");
+
+ if (drop_user_mapping_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseRoleSpec(state, drop_user_mapping_stmt->user);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(drop_user_mapping_stmt->servername));
+}
+
+static void deparseSecLabelStmt(DeparseState *state, SecLabelStmt *sec_label_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "SECURITY LABEL ");
+
+ if (sec_label_stmt->provider != NULL)
+ {
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseAppendStringInfoString(state, quote_identifier(sec_label_stmt->provider));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "ON ");
+
+ switch (sec_label_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ deparseAppendStringInfoString(state, "COLUMN ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_ROLE:
+ deparseAppendStringInfoString(state, "ROLE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseAppendStringInfoString(state, "SUBSCRIPTION ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseTypeName(state, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ deparseTypeName(state, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECT ");
+ deparseValue(state, (union ValUnion *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ default:
+ // Not supported in the parser
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, " IS ");
+
+ if (sec_label_stmt->label != NULL)
+ deparseStringLiteral(state, sec_label_stmt->label);
+ else
+ deparseAppendStringInfoString(state, "NULL");
+}
+
+static void deparseCreateForeignTableStmt(DeparseState *state, CreateForeignTableStmt *create_foreign_table_stmt)
+{
+ ListCell *lc;
+
+ deparseCreateStmt(state, &create_foreign_table_stmt->base, true);
+
+ deparseAppendStringInfoString(state, " SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_foreign_table_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(create_foreign_table_stmt->options) > 0)
+ deparseAlterGenericOptions(state, create_foreign_table_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseImportForeignSchemaStmt(DeparseState *state, ImportForeignSchemaStmt *import_foreign_schema_stmt)
+{
+ deparseAppendStringInfoString(state, "IMPORT FOREIGN SCHEMA ");
+
+ deparseAppendStringInfoString(state, import_foreign_schema_stmt->remote_schema);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (import_foreign_schema_stmt->list_type)
+ {
+ case FDW_IMPORT_SCHEMA_ALL:
+ // Default
+ break;
+ case FDW_IMPORT_SCHEMA_LIMIT_TO:
+ deparseAppendStringInfoString(state, "LIMIT TO (");
+ deparseRelationExprList(state, import_foreign_schema_stmt->table_list);
+ deparseAppendStringInfoString(state, ") ");
+ break;
+ case FDW_IMPORT_SCHEMA_EXCEPT:
+ deparseAppendStringInfoString(state, "EXCEPT (");
+ deparseRelationExprList(state, import_foreign_schema_stmt->table_list);
+ deparseAppendStringInfoString(state, ") ");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "FROM SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(import_foreign_schema_stmt->server_name));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "INTO ");
+ deparseAppendStringInfoString(state, quote_identifier(import_foreign_schema_stmt->local_schema));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseCreateGenericOptions(state, import_foreign_schema_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateTableAsStmt(DeparseState *state, CreateTableAsStmt *create_table_as_stmt)
+{
+ ListCell *lc;
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ deparseOptTemp(state, create_table_as_stmt->into->rel->relpersistence);
+
+ switch (create_table_as_stmt->objtype)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ if (create_table_as_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseIntoClause(state, create_table_as_stmt->into);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "AS ");
+ if (IsA(create_table_as_stmt->query, ExecuteStmt))
+ deparseExecuteStmt(state, castNode(ExecuteStmt, create_table_as_stmt->query));
+ else
+ deparseSelectStmt(state, castNode(SelectStmt, create_table_as_stmt->query), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_table_as_stmt->into->skipData)
+ deparseAppendStringInfoString(state, "WITH NO DATA ");
+
+ removeTrailingSpace(state);
+}
+
+static void deparseViewStmt(DeparseState *state, ViewStmt *view_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (view_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ deparseOptTemp(state, view_stmt->view->relpersistence);
+
+ deparseAppendStringInfoString(state, "VIEW ");
+ deparseRangeVar(state, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(view_stmt->aliases) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, view_stmt->aliases);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseOptWith(state, view_stmt->options);
+
+ deparseAppendStringInfoString(state, "AS ");
+ deparseSelectStmt(state, castNode(SelectStmt, view_stmt->query), DEPARSE_NODE_CONTEXT_NONE);
+
+ switch (view_stmt->withCheckOption)
+ {
+ case NO_CHECK_OPTION:
+ // Default
+ break;
+ case LOCAL_CHECK_OPTION:
+ deparseAppendStringInfoString(state, "WITH LOCAL CHECK OPTION ");
+ break;
+ case CASCADED_CHECK_OPTION:
+ deparseAppendStringInfoString(state, "WITH CHECK OPTION ");
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDropStmt(DeparseState *state, DropStmt *drop_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ deparseAppendStringInfoString(state, "DROP ");
+
+ switch (drop_stmt->removeType)
+ {
+ case OBJECT_ACCESS_METHOD:
+ deparseAppendStringInfoString(state, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ deparseAppendStringInfoString(state, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ deparseAppendStringInfoString(state, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_OPCLASS:
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ break;
+ case OBJECT_OPFAMILY:
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ deparseAppendStringInfoString(state, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ deparseAppendStringInfoString(state, "RULE ");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_TRANSFORM:
+ deparseAppendStringInfoString(state, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, "TRIGGER ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ default:
+ // Other object types are not supported here in the parser
+ Assert(false);
+ }
+
+ if (drop_stmt->concurrent)
+ deparseAppendStringInfoString(state, "CONCURRENTLY ");
+
+ if (drop_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ switch (drop_stmt->removeType)
+ {
+ // drop_type_any_name
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ deparseAnyNameList(state, drop_stmt->objects);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ // drop_type_name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ deparseNameList(state, drop_stmt->objects);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ // drop_type_name_on_any_name
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseColId(state, strVal(llast(l)));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseAnyNameSkipLast(state, l);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_CAST:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ Assert(list_length(l) == 2);
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, castNode(TypeName, lsecond(l)));
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseColId(state, strVal(linitial(l)));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_TRANSFORM:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " LANGUAGE ");
+ deparseColId(state, strVal(lsecond(l)));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_LANGUAGE:
+ deparseNameList(state, drop_stmt->objects);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_AGGREGATE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_OPERATOR:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseOptDropBehavior(state, drop_stmt->behavior);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseGroupingSet(DeparseState *state, GroupingSet *grouping_set)
+{
+ switch(grouping_set->kind)
+ {
+ case GROUPING_SET_EMPTY:
+ deparseAppendStringInfoString(state, "()");
+ break;
+ case GROUPING_SET_SIMPLE:
+ // Not present in raw parse trees
+ Assert(false);
+ break;
+ case GROUPING_SET_ROLLUP:
+ deparseAppendStringInfoString(state, "ROLLUP (");
+ deparseExprList(state, grouping_set->content);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case GROUPING_SET_CUBE:
+ deparseAppendStringInfoString(state, "CUBE (");
+ deparseExprList(state, grouping_set->content);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case GROUPING_SET_SETS:
+ deparseAppendStringInfoString(state, "GROUPING SETS (");
+ deparseGroupByList(state, grouping_set->content);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ }
+}
+
+static void deparseDropTableSpaceStmt(DeparseState *state, DropTableSpaceStmt *drop_table_space_stmt)
+{
+ deparseAppendStringInfoString(state, "DROP TABLESPACE ");
+
+ if (drop_table_space_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAppendStringInfoString(state, drop_table_space_stmt->tablespacename);
+}
+
+static void deparseAlterObjectDependsStmt(DeparseState *state, AlterObjectDependsStmt *alter_object_depends_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (alter_object_depends_stmt->objectType)
+ {
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, "TRIGGER ");
+ deparseColId(state, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ deparseRangeVar(state, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ deparseRangeVar(state, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ // No other object types supported here
+ Assert(false);
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_object_depends_stmt->remove)
+ deparseAppendStringInfoString(state, "NO ");
+
+ deparseAppendStringInfo(state, "DEPENDS ON EXTENSION %s", alter_object_depends_stmt->extname->sval);
+}
+
+static void deparseAlterObjectSchemaStmt(DeparseState *state, AlterObjectSchemaStmt *alter_object_schema_stmt)
+{
+ List *l = NULL;
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (alter_object_schema_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_EXTENSION:
+ deparseAppendStringInfoString(state, "EXTENSION ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(alter_object_schema_stmt->object)));
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_object_schema_stmt->object);
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_object_schema_stmt->object);
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, " SET SCHEMA ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_object_schema_stmt->newschema));
+}
+
+// "alter_table_cmd" in gram.y
+static void deparseAlterTableCmd(DeparseState *state, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+ const char *options = NULL;
+ bool trailing_missing_ok = false;
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AddColumn: /* add column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ deparseAppendStringInfoString(state, "ADD ATTRIBUTE ");
+ else
+ deparseAppendStringInfoString(state, "ADD COLUMN ");
+ break;
+ case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_ColumnDefault: /* alter column default */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ if (alter_table_cmd->def != NULL)
+ options = "SET DEFAULT";
+ else
+ options = "DROP DEFAULT";
+ break;
+ case AT_CookedColumnDefault: /* add a pre-cooked column default */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropNotNull: /* alter column drop not null */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "DROP NOT NULL";
+ break;
+ case AT_SetNotNull: /* alter column set not null */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET NOT NULL";
+ break;
+ case AT_DropExpression: /* alter column drop expression */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "DROP EXPRESSION";
+ trailing_missing_ok = true;
+ break;
+ case AT_CheckNotNull: /* check column is already marked not null */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_SetStatistics: /* alter column set statistics */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET STATISTICS";
+ break;
+ case AT_SetOptions: /* alter column set ( options ) */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET";
+ break;
+ case AT_ResetOptions: /* alter column reset ( options ) */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "RESET";
+ break;
+ case AT_SetStorage: /* alter column set storage */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET STORAGE";
+ break;
+ case AT_SetCompression: /* alter column set compression */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET COMPRESSION";
+ break;
+ case AT_DropColumn: /* drop column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ deparseAppendStringInfoString(state, "DROP ATTRIBUTE ");
+ else
+ deparseAppendStringInfoString(state, "DROP ");
+ break;
+ case AT_AddIndex: /* add index */
+ deparseAppendStringInfoString(state, "ADD INDEX ");
+ break;
+ case AT_ReAddIndex: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddConstraint: /* add constraint */
+ deparseAppendStringInfoString(state, "ADD ");
+ break;
+ case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterConstraint: /* alter constraint */
+ deparseAppendStringInfoString(state, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
+ break;
+ case AT_ValidateConstraint: /* validate constraint */
+ deparseAppendStringInfoString(state, "VALIDATE CONSTRAINT ");
+ break;
+ case AT_AddIndexConstraint: /* add constraint using existing index */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropConstraint: /* drop constraint */
+ deparseAppendStringInfoString(state, "DROP CONSTRAINT ");
+ break;
+ case AT_ReAddComment: /* internal to commands/tablecmds.c */
+ case AT_ReAddStatistics: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterColumnType: /* alter column type */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ deparseAppendStringInfoString(state, "ALTER ATTRIBUTE ");
+ else
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "TYPE";
+ break;
+ case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ // Handled via special case in def handling
+ break;
+ case AT_ChangeOwner: /* change owner */
+ deparseAppendStringInfoString(state, "OWNER TO ");
+ deparseRoleSpec(state, alter_table_cmd->newowner);
+ break;
+ case AT_ClusterOn: /* CLUSTER ON */
+ deparseAppendStringInfoString(state, "CLUSTER ON ");
+ break;
+ case AT_DropCluster: /* SET WITHOUT CLUSTER */
+ deparseAppendStringInfoString(state, "SET WITHOUT CLUSTER ");
+ break;
+ case AT_SetLogged: /* SET LOGGED */
+ deparseAppendStringInfoString(state, "SET LOGGED ");
+ break;
+ case AT_SetUnLogged: /* SET UNLOGGED */
+ deparseAppendStringInfoString(state, "SET UNLOGGED ");
+ break;
+ case AT_DropOids: /* SET WITHOUT OIDS */
+ deparseAppendStringInfoString(state, "SET WITHOUT OIDS ");
+ break;
+ case AT_SetTableSpace: /* SET TABLESPACE */
+ deparseAppendStringInfoString(state, "SET TABLESPACE ");
+ break;
+ case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
+ deparseAppendStringInfoString(state, "SET ");
+ break;
+ case AT_SetAccessMethod:
+ deparseAppendStringInfo(state, "SET ACCESS METHOD ");
+ break;
+ case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
+ deparseAppendStringInfoString(state, "RESET ");
+ break;
+ case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_EnableTrig: /* ENABLE TRIGGER name */
+ deparseAppendStringInfoString(state, "ENABLE TRIGGER ");
+ break;
+ case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
+ deparseAppendStringInfoString(state, "ENABLE ALWAYS TRIGGER ");
+ break;
+ case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
+ deparseAppendStringInfoString(state, "ENABLE REPLICA TRIGGER ");
+ break;
+ case AT_DisableTrig: /* DISABLE TRIGGER name */
+ deparseAppendStringInfoString(state, "DISABLE TRIGGER ");
+ break;
+ case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
+ deparseAppendStringInfoString(state, "ENABLE TRIGGER ALL ");
+ break;
+ case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
+ deparseAppendStringInfoString(state, "DISABLE TRIGGER ALL ");
+ break;
+ case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
+ deparseAppendStringInfoString(state, "ENABLE TRIGGER USER ");
+ break;
+ case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
+ deparseAppendStringInfoString(state, "DISABLE TRIGGER USER ");
+ break;
+ case AT_EnableRule: /* ENABLE RULE name */
+ deparseAppendStringInfoString(state, "ENABLE RULE ");
+ break;
+ case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
+ deparseAppendStringInfoString(state, "ENABLE ALWAYS RULE ");
+ break;
+ case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
+ deparseAppendStringInfoString(state, "ENABLE REPLICA RULE ");
+ break;
+ case AT_DisableRule: /* DISABLE RULE name */
+ deparseAppendStringInfoString(state, "DISABLE RULE ");
+ break;
+ case AT_AddInherit: /* INHERIT parent */
+ deparseAppendStringInfoString(state, "INHERIT ");
+ break;
+ case AT_DropInherit: /* NO INHERIT parent */
+ deparseAppendStringInfoString(state, "NO INHERIT ");
+ break;
+ case AT_AddOf: /* OF */
+ deparseAppendStringInfoString(state, "OF ");
+ break;
+ case AT_DropOf: /* NOT OF */
+ deparseAppendStringInfoString(state, "NOT OF ");
+ break;
+ case AT_ReplicaIdentity: /* REPLICA IDENTITY */
+ deparseAppendStringInfoString(state, "REPLICA IDENTITY ");
+ break;
+ case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
+ deparseAppendStringInfoString(state, "ENABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
+ deparseAppendStringInfoString(state, "DISABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
+ deparseAppendStringInfoString(state, "FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
+ deparseAppendStringInfoString(state, "NO FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_GenericOptions: /* OPTIONS (...) */
+ // Handled in def field handling
+ break;
+ case AT_AttachPartition: /* ATTACH PARTITION */
+ deparseAppendStringInfoString(state, "ATTACH PARTITION ");
+ break;
+ case AT_DetachPartition: /* DETACH PARTITION */
+ deparseAppendStringInfoString(state, "DETACH PARTITION ");
+ break;
+ case AT_DetachPartitionFinalize: /* DETACH PARTITION FINALIZE */
+ deparseAppendStringInfoString(state, "DETACH PARTITION ");
+ break;
+ case AT_AddIdentity: /* ADD IDENTITY */
+ deparseAppendStringInfoString(state, "ALTER ");
+ options = "ADD";
+ // Other details are output via the constraint node (in def field)
+ break;
+ case AT_SetIdentity: /* SET identity column options */
+ deparseAppendStringInfoString(state, "ALTER ");
+ break;
+ case AT_DropIdentity: /* DROP IDENTITY */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "DROP IDENTITY";
+ trailing_missing_ok = true;
+ break;
+ case AT_SetExpression:
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ break;
+ }
+
+ if (alter_table_cmd->missing_ok && !trailing_missing_ok)
+ {
+ if (alter_table_cmd->subtype == AT_AddColumn)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+ else
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ }
+
+ if (alter_table_cmd->name != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(alter_table_cmd->name));
+ deparseAppendStringInfoChar(state, ' ');
+ } else if (alter_table_cmd->subtype == AT_SetAccessMethod)
+ {
+ deparseAppendStringInfoString(state, " DEFAULT");
+ }
+
+ if (alter_table_cmd->num > 0)
+ deparseAppendStringInfo(state, "%d ", alter_table_cmd->num);
+
+ if (options != NULL)
+ {
+ deparseAppendStringInfoString(state, options);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (alter_table_cmd->missing_ok && trailing_missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ deparsePartitionCmd(state, castNode(PartitionCmd, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_DetachPartitionFinalize:
+ deparsePartitionCmd(state, castNode(PartitionCmd, alter_table_cmd->def));
+ deparseAppendStringInfoString(state, "FINALIZE ");
+ break;
+ case AT_AddColumn:
+ case AT_AlterColumnType:
+ deparseColumnDef(state, castNode(ColumnDef, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_ColumnDefault:
+ if (alter_table_cmd->def != NULL)
+ {
+ deparseExpr(state, alter_table_cmd->def, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ break;
+ case AT_SetStatistics:
+ if (alter_table_cmd->def != NULL)
+ deparseSignedIconst(state, alter_table_cmd->def);
+ else
+ deparseAppendStringInfoString(state, "DEFAULT");
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetOptions:
+ case AT_ResetOptions:
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+ deparseRelOptions(state, castNode(List, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetStorage:
+ deparseColId(state, strVal(alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetCompression:
+ if (strcmp(strVal(alter_table_cmd->def), "default") == 0)
+ deparseAppendStringInfoString(state, "DEFAULT");
+ else
+ deparseColId(state, strVal(alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AddIdentity:
+ case AT_AddConstraint:
+ case AT_AlterConstraint:
+ deparseConstraint(state, castNode(Constraint, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetIdentity:
+ deparseAlterIdentityColumnOptionList(state, castNode(List, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AlterColumnGenericOptions:
+ case AT_GenericOptions:
+ deparseAlterGenericOptions(state, castNode(List, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AddInherit:
+ case AT_DropInherit:
+ deparseRangeVar(state, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AddOf:
+ deparseTypeName(state, castNode(TypeName, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_ReplicaIdentity:
+ deparseReplicaIdentityStmt(state, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetExpression:
+ deparseAppendStringInfoString(state, "SET EXPRESSION AS (");
+ deparseExpr(state, alter_table_cmd->def, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ default:
+ Assert(alter_table_cmd->def == NULL);
+ break;
+ }
+
+ deparseOptDropBehavior(state, alter_table_cmd->behavior);
+
+ removeTrailingSpace(state);
+}
+
+static DeparseNodeContext deparseAlterTableObjType(DeparseState *state, ObjectType type)
+{
+ switch (type)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ return DEPARSE_NODE_CONTEXT_ALTER_TYPE;
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ return DEPARSE_NODE_CONTEXT_NONE;
+}
+
+static void deparseAlterTableMoveAllStmt(DeparseState *state, AlterTableMoveAllStmt *move_all_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER ");
+ deparseAlterTableObjType(state, move_all_stmt->objtype);
+
+ deparseAppendStringInfoString(state, "ALL IN TABLESPACE ");
+ deparseAppendStringInfoString(state, move_all_stmt->orig_tablespacename);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (move_all_stmt->roles)
+ {
+ deparseAppendStringInfoString(state, "OWNED BY ");
+ deparseRoleList(state, move_all_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "SET TABLESPACE ");
+ deparseAppendStringInfoString(state, move_all_stmt->new_tablespacename);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (move_all_stmt->nowait)
+ {
+ deparseAppendStringInfoString(state, "NOWAIT");
+ }
+}
+
+static void deparseAlterTableStmt(DeparseState *state, AlterTableStmt *alter_table_stmt)
+{
+ ListCell *lc;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+ DeparseNodeContext context = deparseAlterTableObjType(state, alter_table_stmt->objtype);
+
+ if (alter_table_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseRangeVar(state, alter_table_stmt->relation, context);
+ deparseAppendStringInfoChar(state, ' ');
+
+ parent_level = deparseStateIncreaseNestingLevel(state);
+ foreach(lc, alter_table_stmt->cmds)
+ {
+ deparseAlterTableCmd(state, castNode(AlterTableCmd, lfirst(lc)), context);
+ if (lnext(alter_table_stmt->cmds, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+static void deparseAlterTableSpaceOptionsStmt(DeparseState *state, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER TABLESPACE ");
+ deparseColId(state, alter_table_space_options_stmt->tablespacename);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_table_space_options_stmt->isReset)
+ deparseAppendStringInfoString(state, "RESET ");
+ else
+ deparseAppendStringInfoString(state, "SET ");
+
+ deparseRelOptions(state, alter_table_space_options_stmt->options);
+}
+
+// "AlterDomainStmt" in gram.y
+static void deparseAlterDomainStmt(DeparseState *state, AlterDomainStmt *alter_domain_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER DOMAIN ");
+ deparseAnyName(state, alter_domain_stmt->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (alter_domain_stmt->subtype)
+ {
+ case 'T':
+ if (alter_domain_stmt->def != NULL)
+ {
+ deparseAppendStringInfoString(state, "SET DEFAULT ");
+ deparseExpr(state, alter_domain_stmt->def, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "DROP DEFAULT");
+ }
+ break;
+ case 'N':
+ deparseAppendStringInfoString(state, "DROP NOT NULL");
+ break;
+ case 'O':
+ deparseAppendStringInfoString(state, "SET NOT NULL");
+ break;
+ case 'C':
+ deparseAppendStringInfoString(state, "ADD ");
+ deparseConstraint(state, castNode(Constraint, alter_domain_stmt->def));
+ break;
+ case 'X':
+ deparseAppendStringInfoString(state, "DROP CONSTRAINT ");
+ if (alter_domain_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_domain_stmt->name));
+ if (alter_domain_stmt->behavior == DROP_CASCADE)
+ deparseAppendStringInfoString(state, " CASCADE");
+ break;
+ case 'V':
+ deparseAppendStringInfoString(state, "VALIDATE CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_domain_stmt->name));
+ break;
+ default:
+ // No other subtypes supported by the parser
+ Assert(false);
+ }
+}
+
+static void deparseRenameStmt(DeparseState *state, RenameStmt *rename_stmt)
+{
+ List *l = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_DOMCONSTRAINT:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_ROLE:
+ deparseAppendStringInfoString(state, "ROLE ");
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ break;
+ case OBJECT_OPCLASS:
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ deparseAppendStringInfoString(state, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseAppendStringInfoString(state, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_TABCONSTRAINT:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_COLUMN:
+ switch (rename_stmt->relationType)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ default:
+ Assert(false);
+ }
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_RULE:
+ deparseAppendStringInfoString(state, "RULE ");
+ break;
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, "TRIGGER ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_ATTRIBUTE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (rename_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAnyName(state, castNode(List, rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, rename_stmt->object);
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(l))));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_POLICY:
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseColId(state, strVal(rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_COLUMN:
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME COLUMN ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, quote_identifier(strVal(rename_stmt->object)));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_DOMAIN:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TYPE:
+ deparseAnyName(state, castNode(List, rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_ATTRIBUTE:
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
+ deparseAppendStringInfoString(state, " RENAME ATTRIBUTE ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "TO ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->newname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseOptDropBehavior(state, rename_stmt->behavior);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseTransactionStmt(DeparseState *state, TransactionStmt *transaction_stmt)
+{
+ ListCell *lc;
+ switch (transaction_stmt->kind)
+ {
+ case TRANS_STMT_BEGIN:
+ deparseAppendStringInfoString(state, "BEGIN ");
+ deparseTransactionModeList(state, transaction_stmt->options);
+ break;
+ case TRANS_STMT_START:
+ deparseAppendStringInfoString(state, "START TRANSACTION ");
+ deparseTransactionModeList(state, transaction_stmt->options);
+ break;
+ case TRANS_STMT_COMMIT:
+ deparseAppendStringInfoString(state, "COMMIT ");
+ if (transaction_stmt->chain)
+ deparseAppendStringInfoString(state, "AND CHAIN ");
+ break;
+ case TRANS_STMT_ROLLBACK:
+ deparseAppendStringInfoString(state, "ROLLBACK ");
+ if (transaction_stmt->chain)
+ deparseAppendStringInfoString(state, "AND CHAIN ");
+ break;
+ case TRANS_STMT_SAVEPOINT:
+ deparseAppendStringInfoString(state, "SAVEPOINT ");
+ deparseAppendStringInfoString(state, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_RELEASE:
+ deparseAppendStringInfoString(state, "RELEASE ");
+ deparseAppendStringInfoString(state, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_ROLLBACK_TO:
+ deparseAppendStringInfoString(state, "ROLLBACK ");
+ deparseAppendStringInfoString(state, "TO SAVEPOINT ");
+ deparseAppendStringInfoString(state, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_PREPARE:
+ deparseAppendStringInfoString(state, "PREPARE TRANSACTION ");
+ deparseStringLiteral(state, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_COMMIT_PREPARED:
+ deparseAppendStringInfoString(state, "COMMIT PREPARED ");
+ deparseStringLiteral(state, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_ROLLBACK_PREPARED:
+ deparseAppendStringInfoString(state, "ROLLBACK PREPARED ");
+ deparseStringLiteral(state, transaction_stmt->gid);
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+// Determine if we hit SET TIME ZONE INTERVAL, that has special syntax not
+// supported for other SET statements
+static bool isSetTimeZoneInterval(VariableSetStmt* stmt)
+{
+ if (!(strcmp(stmt->name, "timezone") == 0 &&
+ list_length(stmt->args) == 1 &&
+ IsA(linitial(stmt->args), TypeCast)))
+ return false;
+
+ TypeName* typeName = castNode(TypeCast, linitial(stmt->args))->typeName;
+
+ return (list_length(typeName->names) == 2 &&
+ strcmp(strVal(linitial(typeName->names)), "pg_catalog") == 0 &&
+ strcmp(strVal(llast(typeName->names)), "interval") == 0);
+}
+
+static void deparseVariableSetStmt(DeparseState *state, VariableSetStmt* variable_set_stmt)
+{
+ ListCell *lc;
+
+ switch (variable_set_stmt->kind)
+ {
+ case VAR_SET_VALUE: /* SET var = value */
+ deparseAppendStringInfoString(state, "SET ");
+ if (variable_set_stmt->is_local)
+ deparseAppendStringInfoString(state, "LOCAL ");
+ if (isSetTimeZoneInterval(variable_set_stmt))
+ {
+ deparseAppendStringInfoString(state, "TIME ZONE ");
+ deparseVarList(state, variable_set_stmt->args);
+ }
+ else
+ {
+ deparseVarName(state, variable_set_stmt->name);
+ deparseAppendStringInfoString(state, " TO ");
+ deparseVarList(state, variable_set_stmt->args);
+ }
+ break;
+ case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
+ deparseAppendStringInfoString(state, "SET ");
+ if (variable_set_stmt->is_local)
+ deparseAppendStringInfoString(state, "LOCAL ");
+ deparseVarName(state, variable_set_stmt->name);
+ deparseAppendStringInfoString(state, " TO DEFAULT");
+ break;
+ case VAR_SET_CURRENT: /* SET var FROM CURRENT */
+ deparseAppendStringInfoString(state, "SET ");
+ if (variable_set_stmt->is_local)
+ deparseAppendStringInfoString(state, "LOCAL ");
+ deparseVarName(state, variable_set_stmt->name);
+ deparseAppendStringInfoString(state, " FROM CURRENT");
+ break;
+ case VAR_SET_MULTI: /* special case for SET TRANSACTION ... */
+ Assert(variable_set_stmt->name != NULL);
+ deparseAppendStringInfoString(state, "SET ");
+ if (variable_set_stmt->is_local)
+ deparseAppendStringInfoString(state, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
+ {
+ deparseAppendStringInfoString(state, "TRANSACTION ");
+ deparseTransactionModeList(state, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
+ {
+ deparseAppendStringInfoString(state, "SESSION CHARACTERISTICS AS TRANSACTION ");
+ deparseTransactionModeList(state, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
+ {
+ deparseAppendStringInfoString(state, "TRANSACTION SNAPSHOT ");
+ deparseStringLiteral(state, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case VAR_RESET: /* RESET var */
+ deparseAppendStringInfoString(state, "RESET ");
+ deparseVarName(state, variable_set_stmt->name);
+ break;
+ case VAR_RESET_ALL: /* RESET ALL */
+ deparseAppendStringInfoString(state, "RESET ALL");
+ break;
+ }
+}
+
+static void deparseDropdbStmt(DeparseState *state, DropdbStmt *dropdb_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "DROP DATABASE ");
+ if (dropdb_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAppendStringInfoString(state, quote_identifier(dropdb_stmt->dbname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(dropdb_stmt->options) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, dropdb_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "force") == 0)
+ deparseAppendStringInfoString(state, "FORCE");
+ else
+ Assert(false); // Currently there are other supported values
+
+ if (lnext(dropdb_stmt->options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseVacuumStmt(DeparseState *state, VacuumStmt *vacuum_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ if (vacuum_stmt->is_vacuumcmd)
+ deparseAppendStringInfoString(state, "VACUUM ");
+ else
+ deparseAppendStringInfoString(state, "ANALYZE ");
+
+ deparseUtilityOptionList(state, vacuum_stmt->options);
+
+ foreach(lc, vacuum_stmt->rels)
+ {
+ Assert(IsA(lfirst(lc), VacuumRelation));
+ VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
+
+ deparseRangeVar(state, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(rel->va_cols) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc2, rel->va_cols)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc2))));
+ if (lnext(rel->va_cols, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ if (lnext(vacuum_stmt->rels, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseLoadStmt(DeparseState *state, LoadStmt *load_stmt)
+{
+ deparseAppendStringInfoString(state, "LOAD ");
+ deparseStringLiteral(state, load_stmt->filename);
+}
+
+static void deparseLockStmt(DeparseState *state, LockStmt *lock_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "LOCK TABLE ");
+
+ deparseRelationExprList(state, lock_stmt->relations);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (lock_stmt->mode != AccessExclusiveLock)
+ {
+ deparseAppendStringInfoString(state, "IN ");
+ switch (lock_stmt->mode)
+ {
+ case AccessShareLock:
+ deparseAppendStringInfoString(state, "ACCESS SHARE ");
+ break;
+ case RowShareLock:
+ deparseAppendStringInfoString(state, "ROW SHARE ");
+ break;
+ case RowExclusiveLock:
+ deparseAppendStringInfoString(state, "ROW EXCLUSIVE ");
+ break;
+ case ShareUpdateExclusiveLock:
+ deparseAppendStringInfoString(state, "SHARE UPDATE EXCLUSIVE ");
+ break;
+ case ShareLock:
+ deparseAppendStringInfoString(state, "SHARE ");
+ break;
+ case ShareRowExclusiveLock:
+ deparseAppendStringInfoString(state, "SHARE ROW EXCLUSIVE ");
+ break;
+ case ExclusiveLock:
+ deparseAppendStringInfoString(state, "EXCLUSIVE ");
+ break;
+ case AccessExclusiveLock:
+ deparseAppendStringInfoString(state, "ACCESS EXCLUSIVE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+ deparseAppendStringInfoString(state, "MODE ");
+ }
+
+ if (lock_stmt->nowait)
+ deparseAppendStringInfoString(state, "NOWAIT ");
+
+ removeTrailingSpace(state);
+}
+
+static void deparseConstraintsSetStmt(DeparseState *state, ConstraintsSetStmt *constraints_set_stmt)
+{
+ deparseAppendStringInfoString(state, "SET CONSTRAINTS ");
+
+ if (list_length(constraints_set_stmt->constraints) > 0)
+ {
+ deparseQualifiedNameList(state, constraints_set_stmt->constraints);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ALL ");
+ }
+
+ if (constraints_set_stmt->deferred)
+ deparseAppendStringInfoString(state, "DEFERRED");
+ else
+ deparseAppendStringInfoString(state, "IMMEDIATE");
+}
+
+static void deparseExplainStmt(DeparseState *state, ExplainStmt *explain_stmt)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ deparseAppendPartGroup(state, "EXPLAIN", DEPARSE_PART_NO_INDENT);
+
+ deparseUtilityOptionList(state, explain_stmt->options);
+
+ deparseExplainableStmt(state, explain_stmt->query);
+}
+
+static void deparseCopyStmt(DeparseState *state, CopyStmt *copy_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ deparseAppendPartGroup(state, "COPY", DEPARSE_PART_INDENT);
+
+ if (copy_stmt->relation != NULL)
+ {
+ deparseRangeVar(state, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(copy_stmt->attlist) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, copy_stmt->attlist);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (copy_stmt->query != NULL)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparsePreparableStmt(state, copy_stmt->query);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (copy_stmt->is_from)
+ deparseAppendStringInfoString(state, "FROM ");
+ else
+ deparseAppendStringInfoString(state, "TO ");
+
+ if (copy_stmt->is_program)
+ deparseAppendStringInfoString(state, "PROGRAM ");
+
+ if (copy_stmt->filename != NULL)
+ {
+ deparseStringLiteral(state, copy_stmt->filename);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ if (copy_stmt->is_from)
+ deparseAppendStringInfoString(state, "STDIN ");
+ else
+ deparseAppendStringInfoString(state, "STDOUT ");
+ }
+
+ if (list_length(copy_stmt->options) > 0)
+ {
+ // In some cases, equivalent expressions may have slightly different parse trees for `COPY`
+ // statements. For example the following two statements result in different (but equivalent) parse
+ // trees:
+ //
+ // - COPY foo FROM STDIN CSV FREEZE
+ // - COPY foo FROM STDIN WITH (FORMAT CSV, FREEZE)
+ //
+ // In order to make sure we deparse to the "correct" version, we always try to deparse to the older
+ // compact syntax first.
+ //
+ // The old syntax can be seen here in the Postgres 8.4 Reference:
+ // https://www.postgresql.org/docs/8.4/sql-copy.html
+
+ bool old_fmt = true;
+
+ // Loop over the options to see if any require the new `WITH (...)` syntax.
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
+ {}
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {}
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
+ {}
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
+ {}
+ else
+ {
+ old_fmt = false;
+ break;
+ }
+ }
+
+ // Branch to differing output modes, depending on if we can use the old syntax.
+ if (old_fmt) {
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "FREEZE ");
+ }
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "HEADER ");
+ }
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
+ {
+ deparseAppendStringInfoString(state, "CSV ");
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
+ {
+ deparseAppendStringInfoString(state, "FORCE QUOTE ");
+ deparseColumnList(state, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ // This isn't reachable, the conditions here are exactly the same as the first loop above.
+ Assert(false);
+ }
+ }
+ } else {
+ deparseAppendStringInfoString(state, "WITH (");
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "format") == 0)
+ {
+ deparseAppendStringInfoString(state, "FORMAT ");
+
+ char *format = strVal(def_elem->arg);
+ if (strcmp(format, "binary") == 0)
+ deparseAppendStringInfoString(state, "BINARY");
+ else if (strcmp(format, "csv") == 0)
+ deparseAppendStringInfoString(state, "CSV");
+ else if (strcmp(format, "text") == 0)
+ deparseAppendStringInfoString(state, "TEXT");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "freeze") == 0)
+ {
+ deparseAppendStringInfoString(state, "FREEZE");
+ deparseOptBoolean(state, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
+ {
+ deparseAppendStringInfoString(state, "DELIMITER ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "null") == 0)
+ {
+ deparseAppendStringInfoString(state, "NULL ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "header") == 0)
+ {
+ deparseAppendStringInfoString(state, "HEADER");
+ deparseOptBoolean(state, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "quote") == 0)
+ {
+ deparseAppendStringInfoString(state, "QUOTE ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "escape") == 0)
+ {
+ deparseAppendStringInfoString(state, "ESCAPE ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
+ {
+ deparseAppendStringInfoString(state, "FORCE_QUOTE ");
+ if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAppendStringInfoChar(state, '*');
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, castNode(List, def_elem->arg));
+ deparseAppendStringInfoChar(state, ')');
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
+ {
+ deparseAppendStringInfoString(state, "FORCE_NOT_NULL ");
+
+ if (IsA(def_elem->arg, A_Star))
+ deparseAStar(state, castNode(A_Star, def_elem->arg));
+ else
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, castNode(List, def_elem->arg));
+ deparseAppendStringInfoChar(state, ')');
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_null") == 0)
+ {
+ deparseAppendStringInfoString(state, "FORCE_NULL ");
+
+ if (IsA(def_elem->arg, A_Star))
+ deparseAStar(state, castNode(A_Star, def_elem->arg));
+ else
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, castNode(List, def_elem->arg));
+ deparseAppendStringInfoChar(state, ')');
+ }
+ }
+ else if (strcmp(def_elem->defname, "encoding") == 0)
+ {
+ deparseAppendStringInfoString(state, "ENCODING ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL)
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (def_elem->arg == NULL)
+ {
+ // Nothing
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseOptBooleanOrString(state, strVal(def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ {
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAStar(state, castNode(A_Star, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ List *l = castNode(List, def_elem->arg);
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc2, l)
+ {
+ deparseOptBooleanOrString(state, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+ }
+
+ if (lnext(copy_stmt->options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ }
+
+ deparseWhereClause(state, copy_stmt->whereClause);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDoStmt(DeparseState *state, DoStmt *do_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "DO ");
+
+ foreach (lc, do_stmt->args)
+ {
+ DefElem *defel = castNode(DefElem, lfirst(lc));
+ if (strcmp(defel->defname, "language") == 0)
+ {
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(defel->arg)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (strcmp(defel->defname, "as") == 0)
+ {
+ char *strval = strVal(defel->arg);
+ const char *delim = "$$";
+ if (strstr(strval, "$$") != NULL)
+ delim = "$outer$";
+ deparseAppendStringInfoString(state, delim);
+ deparseAppendStringInfoString(state, strval);
+ deparseAppendStringInfoString(state, delim);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDiscardStmt(DeparseState *state, DiscardStmt *discard_stmt)
+{
+ deparseAppendStringInfoString(state, "DISCARD ");
+ switch (discard_stmt->target)
+ {
+ case DISCARD_ALL:
+ deparseAppendStringInfoString(state, "ALL");
+ break;
+ case DISCARD_PLANS:
+ deparseAppendStringInfoString(state, "PLANS");
+ break;
+ case DISCARD_SEQUENCES:
+ deparseAppendStringInfoString(state, "SEQUENCES");
+ break;
+ case DISCARD_TEMP:
+ deparseAppendStringInfoString(state, "TEMP");
+ break;
+ }
+}
+
+static void deparseDefineStmt(DeparseState *state, DefineStmt *define_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (define_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ default:
+ // This shouldn't happen
+ Assert(false);
+ break;
+ }
+
+ if (define_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseFuncName(state, define_stmt->defnames);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAnyOperator(state, define_stmt->defnames);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_COLLATION:
+ deparseAnyName(state, define_stmt->defnames);
+ break;
+ default:
+ Assert(false);
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
+ {
+ deparseAggrArgs(state, define_stmt->args);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (define_stmt->kind == OBJECT_COLLATION &&
+ list_length(define_stmt->definition) == 1 &&
+ strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
+ {
+ deparseAppendStringInfoString(state, "FROM ");
+ deparseAnyName(state, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
+ }
+ else if (list_length(define_stmt->definition) > 0)
+ {
+ deparseDefinition(state, define_stmt->definition);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCompositeTypeStmt(DeparseState *state, CompositeTypeStmt *composite_type_stmt)
+{
+ ListCell *lc;
+ RangeVar *typevar;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE TYPE ");
+ deparseRangeVar(state, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
+
+ deparseAppendStringInfoString(state, " AS (");
+ parent_level = deparseStateIncreaseNestingLevel(state);
+ foreach(lc, composite_type_stmt->coldeflist)
+ {
+ deparseColumnDef(state, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(composite_type_stmt->coldeflist, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseCreateEnumStmt(DeparseState *state, CreateEnumStmt *create_enum_stmt)
+{
+ ListCell *lc;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE TYPE ");
+
+ deparseAnyName(state, create_enum_stmt->typeName);
+ deparseAppendStringInfoString(state, " AS ENUM (");
+ parent_level = deparseStateIncreaseNestingLevel(state);
+ foreach(lc, create_enum_stmt->vals)
+ {
+ deparseStringLiteral(state, strVal(lfirst(lc)));
+ if (lnext(create_enum_stmt->vals, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseCreateRangeStmt(DeparseState *state, CreateRangeStmt *create_range_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE TYPE ");
+ deparseAnyName(state, create_range_stmt->typeName);
+ deparseAppendStringInfoString(state, " AS RANGE ");
+ deparseDefinition(state, create_range_stmt->params);
+}
+
+static void deparseAlterEnumStmt(DeparseState *state, AlterEnumStmt *alter_enum_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER TYPE ");
+ deparseAnyName(state, alter_enum_stmt->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_enum_stmt->oldVal == NULL)
+ {
+ deparseAppendStringInfoString(state, "ADD VALUE ");
+ if (alter_enum_stmt->skipIfNewValExists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseStringLiteral(state, alter_enum_stmt->newVal);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_enum_stmt->newValNeighbor)
+ {
+ if (alter_enum_stmt->newValIsAfter)
+ deparseAppendStringInfoString(state, "AFTER ");
+ else
+ deparseAppendStringInfoString(state, "BEFORE ");
+ deparseStringLiteral(state, alter_enum_stmt->newValNeighbor);
+ }
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "RENAME VALUE ");
+ deparseStringLiteral(state, alter_enum_stmt->oldVal);
+ deparseAppendStringInfoString(state, " TO ");
+ deparseStringLiteral(state, alter_enum_stmt->newVal);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterExtensionStmt(DeparseState *state, AlterExtensionStmt *alter_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER EXTENSION ");
+ deparseColId(state, alter_extension_stmt->extname);
+ deparseAppendStringInfoString(state, " UPDATE ");
+ foreach (lc, alter_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ deparseAppendStringInfoString(state, "TO ");
+ deparseNonReservedWordOrSconst(state, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterExtensionContentsStmt(DeparseState *state, AlterExtensionContentsStmt *alter_extension_contents_stmt)
+{
+ List *l = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER EXTENSION ");
+ deparseColId(state, alter_extension_contents_stmt->extname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_extension_contents_stmt->action == 1)
+ deparseAppendStringInfoString(state, "ADD ");
+ else if (alter_extension_contents_stmt->action == -1)
+ deparseAppendStringInfoString(state, "DROP ");
+ else
+ Assert(false);
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ deparseAppendStringInfoString(state, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ deparseAppendStringInfoString(state, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ break;
+ case OBJECT_OPCLASS:
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ break;
+ case OBJECT_TRANSFORM:
+ deparseAppendStringInfoString(state, "TRANSFORM ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ default:
+ // No other object types are supported here in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ // any_name
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_TABLE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ deparseAnyName(state, castNode(List, alter_extension_contents_stmt->object));
+ break;
+ // name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_LANGUAGE:
+ case OBJECT_SCHEMA:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ deparseColId(state, strVal(alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, castNode(TypeName, lsecond(l)));
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ deparseTypeName(state, castNode(TypeName, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseColId(state, strVal(linitial(l)));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " LANGUAGE ");
+ deparseColId(state, strVal(lsecond(l)));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparseAccessPriv(DeparseState *state, AccessPriv *access_priv)
+{
+ ListCell *lc;
+
+ if (access_priv->priv_name != NULL)
+ {
+ if (strcmp(access_priv->priv_name, "select") == 0)
+ deparseAppendStringInfoString(state, "select");
+ else if (strcmp(access_priv->priv_name, "references") == 0)
+ deparseAppendStringInfoString(state, "references");
+ else if (strcmp(access_priv->priv_name, "create") == 0)
+ deparseAppendStringInfoString(state, "create");
+ else
+ deparseAppendStringInfoString(state, quote_identifier(access_priv->priv_name));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ALL");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(access_priv->cols) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, access_priv->cols);
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseGrantStmt(DeparseState *state, GrantStmt *grant_stmt)
+{
+ ListCell *lc;
+ if (grant_stmt->is_grant)
+ deparseAppendStringInfoString(state, "GRANT ");
+ else
+ deparseAppendStringInfoString(state, "REVOKE ");
+
+ if (!grant_stmt->is_grant && grant_stmt->grant_option)
+ deparseAppendStringInfoString(state, "GRANT OPTION FOR ");
+
+ if (list_length(grant_stmt->privileges) > 0)
+ {
+ foreach(lc, grant_stmt->privileges)
+ {
+ deparseAccessPriv(state, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_stmt->privileges, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ALL ");
+ }
+
+ deparseAppendStringInfoString(state, "ON ");
+
+ deparsePrivilegeTarget(state, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (grant_stmt->is_grant)
+ deparseAppendStringInfoString(state, "TO ");
+ else
+ deparseAppendStringInfoString(state, "FROM ");
+
+ foreach(lc, grant_stmt->grantees)
+ {
+ deparseRoleSpec(state, castNode(RoleSpec, lfirst(lc)));
+ if (lnext(grant_stmt->grantees, lc))
+ deparseAppendStringInfoChar(state, ',');
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (grant_stmt->is_grant && grant_stmt->grant_option)
+ deparseAppendStringInfoString(state, "WITH GRANT OPTION ");
+
+ deparseOptDropBehavior(state, grant_stmt->behavior);
+
+ if (grant_stmt->grantor)
+ {
+ deparseAppendStringInfoString(state, "GRANTED BY ");
+ deparseRoleSpec(state, castNode(RoleSpec, grant_stmt->grantor));
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseGrantRoleStmt(DeparseState *state, GrantRoleStmt *grant_role_stmt)
+{
+ ListCell *lc;
+
+ if (grant_role_stmt->is_grant)
+ deparseAppendStringInfoString(state, "GRANT ");
+ else
+ deparseAppendStringInfoString(state, "REVOKE ");
+
+ if (!grant_role_stmt->is_grant && list_length(grant_role_stmt->opt)) {
+ DefElem *defelem = castNode(DefElem, linitial(grant_role_stmt->opt));
+ Assert(!castNode(Boolean, defelem->arg)->boolval);
+
+ if (strcmp("admin", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "ADMIN ");
+ } else if (strcmp("inherit", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "INHERIT ");
+ } else if (strcmp("set", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "SET ");
+ }
+
+ deparseAppendStringInfoString(state, "OPTION FOR ");
+ }
+
+ foreach(lc, grant_role_stmt->granted_roles)
+ {
+ deparseAccessPriv(state, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_role_stmt->granted_roles, lc))
+ deparseAppendStringInfoChar(state, ',');
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (grant_role_stmt->is_grant)
+ deparseAppendStringInfoString(state, "TO ");
+ else
+ deparseAppendStringInfoString(state, "FROM ");
+
+ deparseRoleList(state, grant_role_stmt->grantee_roles);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (grant_role_stmt->is_grant) {
+ if (list_length(grant_role_stmt->opt) > 0) {
+ deparseAppendStringInfoString(state, "WITH ");
+ }
+
+ foreach(lc, grant_role_stmt->opt) {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp("admin", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "ADMIN ");
+ deparseAppendStringInfoString(state, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ } else if (strcmp("inherit", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "INHERIT ");
+ deparseAppendStringInfoString(state, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ } else if (strcmp("set", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "SET ");
+ deparseAppendStringInfoString(state, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ }
+
+ if (lnext(grant_role_stmt->opt, lc)) {
+ deparseAppendStringInfoChar(state, ',');
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ if (grant_role_stmt->grantor)
+ {
+ deparseAppendStringInfoString(state, "GRANTED BY ");
+ deparseRoleSpec(state, castNode(RoleSpec, grant_role_stmt->grantor));
+ }
+
+ if (grant_role_stmt->behavior == DROP_CASCADE) {
+ deparseAppendStringInfoString(state, "CASCADE ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDropRoleStmt(DeparseState *state, DropRoleStmt *drop_role_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "DROP ROLE ");
+
+ if (drop_role_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseRoleList(state, drop_role_stmt->roles);
+}
+
+static void deparseIndexStmt(DeparseState *state, IndexStmt *index_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (index_stmt->unique)
+ deparseAppendStringInfoString(state, "UNIQUE ");
+
+ deparseAppendStringInfoString(state, "INDEX ");
+
+ if (index_stmt->concurrent)
+ deparseAppendStringInfoString(state, "CONCURRENTLY ");
+
+ if (index_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ if (index_stmt->idxname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(index_stmt->idxname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "ON", DEPARSE_PART_INDENT);
+ deparseRangeVar(state, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (index_stmt->accessMethod != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(index_stmt->accessMethod));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoChar(state, '(');
+ foreach (lc, index_stmt->indexParams)
+ {
+ deparseIndexElem(state, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexParams, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+
+ if (list_length(index_stmt->indexIncludingParams) > 0)
+ {
+ deparseAppendStringInfoString(state, "INCLUDE (");
+ foreach (lc, index_stmt->indexIncludingParams)
+ {
+ deparseIndexElem(state, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexIncludingParams, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (index_stmt->nulls_not_distinct)
+ {
+ deparseAppendStringInfoString(state, "NULLS NOT DISTINCT ");
+ }
+
+ deparseOptWith(state, index_stmt->options);
+
+ if (index_stmt->tableSpace != NULL)
+ {
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseAppendStringInfoString(state, quote_identifier(index_stmt->tableSpace));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseWhereClause(state, index_stmt->whereClause);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterOpFamilyStmt(DeparseState *state, AlterOpFamilyStmt *alter_op_family_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER OPERATOR FAMILY ");
+ deparseAnyName(state, alter_op_family_stmt->opfamilyname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_op_family_stmt->amname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_op_family_stmt->isDrop)
+ deparseAppendStringInfoString(state, "DROP ");
+ else
+ deparseAppendStringInfoString(state, "ADD ");
+
+ deparseOpclassItemList(state, alter_op_family_stmt->items);
+}
+
+static void deparsePrepareStmt(DeparseState *state, PrepareStmt *prepare_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "PREPARE ");
+ deparseColId(state, prepare_stmt->name);
+ if (list_length(prepare_stmt->argtypes) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeList(state, prepare_stmt->argtypes);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ deparseAppendStringInfoString(state, " AS ");
+ deparsePreparableStmt(state, prepare_stmt->query);
+}
+
+static void deparseExecuteStmt(DeparseState *state, ExecuteStmt *execute_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "EXECUTE ");
+ deparseAppendStringInfoString(state, quote_identifier(execute_stmt->name));
+ if (list_length(execute_stmt->params) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseExprList(state, execute_stmt->params);
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+static void deparseDeallocateStmt(DeparseState *state, DeallocateStmt *deallocate_stmt)
+{
+ deparseAppendStringInfoString(state, "DEALLOCATE ");
+ if (deallocate_stmt->name != NULL)
+ deparseAppendStringInfoString(state, quote_identifier(deallocate_stmt->name));
+ else
+ deparseAppendStringInfoString(state, "ALL");
+}
+
+// "AlterOptRoleElem" in gram.y
+static void deparseAlterRoleElem(DeparseState *state, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "password") == 0)
+ {
+ deparseAppendStringInfoString(state, "PASSWORD ");
+ if (def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NULL");
+ }
+ else if (IsA(def_elem->arg, ParamRef))
+ {
+ deparseParamRef(state, castNode(ParamRef, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "connectionlimit") == 0)
+ {
+ deparseAppendStringInfo(state, "CONNECTION LIMIT %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validUntil") == 0)
+ {
+ deparseAppendStringInfoString(state, "VALID UNTIL ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "SUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOSUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "CREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOCREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "REPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOREPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "CREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOCREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "LOGIN");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOLOGIN");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "BYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOBYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "INHERIT");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOINHERIT");
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "CreateOptRoleElem" in gram.y
+static void deparseCreateRoleElem(DeparseState *state, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "sysid") == 0)
+ {
+ deparseAppendStringInfo(state, "SYSID %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "adminmembers") == 0)
+ {
+ deparseAppendStringInfoString(state, "ADMIN ");
+ deparseRoleList(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "rolemembers") == 0)
+ {
+ deparseAppendStringInfoString(state, "ROLE ");
+ deparseRoleList(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "addroleto") == 0)
+ {
+ deparseAppendStringInfoString(state, "IN ROLE ");
+ deparseRoleList(state, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ deparseAlterRoleElem(state, def_elem);
+ }
+}
+
+static void deparseCreatePLangStmt(DeparseState *state, CreatePLangStmt *create_p_lang_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (create_p_lang_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ if (create_p_lang_stmt->pltrusted)
+ deparseAppendStringInfoString(state, "TRUSTED ");
+
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(state, create_p_lang_stmt->plname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "HANDLER ");
+ deparseHandlerName(state, create_p_lang_stmt->plhandler);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_p_lang_stmt->plinline)
+ {
+ deparseAppendStringInfoString(state, "INLINE ");
+ deparseHandlerName(state, create_p_lang_stmt->plinline);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_p_lang_stmt->plvalidator)
+ {
+ deparseAppendStringInfoString(state, "VALIDATOR ");
+ deparseHandlerName(state, create_p_lang_stmt->plvalidator);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateRoleStmt(DeparseState *state, CreateRoleStmt *create_role_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ switch (create_role_stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ deparseAppendStringInfoString(state, "ROLE ");
+ break;
+ case ROLESTMT_USER:
+ deparseAppendStringInfoString(state, "USER ");
+ break;
+ case ROLESTMT_GROUP:
+ deparseAppendStringInfoString(state, "GROUP ");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, quote_identifier(create_role_stmt->role));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_role_stmt->options != NULL)
+ {
+ deparseAppendStringInfoString(state, "WITH ");
+ foreach (lc, create_role_stmt->options)
+ {
+ deparseCreateRoleElem(state, castNode(DefElem, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterRoleStmt(DeparseState *state, AlterRoleStmt *alter_role_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
+ {
+ deparseAppendStringInfoString(state, "GROUP ");
+ deparseRoleSpec(state, alter_role_stmt->role);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_role_stmt->action == 1)
+ {
+ deparseAppendStringInfoString(state, "ADD USER ");
+ }
+ else if (alter_role_stmt->action == -1)
+ {
+ deparseAppendStringInfoString(state, "DROP USER ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseRoleList(state, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ROLE ");
+ deparseRoleSpec(state, alter_role_stmt->role);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "WITH ");
+ foreach (lc, alter_role_stmt->options)
+ {
+ deparseAlterRoleElem(state, castNode(DefElem, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDeclareCursorStmt(DeparseState *state, DeclareCursorStmt *declare_cursor_stmt)
+{
+ deparseAppendStringInfoString(state, "DECLARE ");
+ deparseAppendStringInfoString(state, quote_identifier(declare_cursor_stmt->portalname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
+ deparseAppendStringInfoString(state, "BINARY ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
+ deparseAppendStringInfoString(state, "SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
+ deparseAppendStringInfoString(state, "NO SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
+ deparseAppendStringInfoString(state, "INSENSITIVE ");
+
+ deparseAppendStringInfoString(state, "CURSOR ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
+ deparseAppendStringInfoString(state, "WITH HOLD ");
+
+ deparseAppendStringInfoString(state, "FOR ");
+
+ deparseSelectStmt(state, castNode(SelectStmt, declare_cursor_stmt->query), DEPARSE_NODE_CONTEXT_NONE);
+}
+
+static void deparseFetchStmt(DeparseState *state, FetchStmt *fetch_stmt)
+{
+ if (fetch_stmt->ismove)
+ deparseAppendStringInfoString(state, "MOVE ");
+ else
+ deparseAppendStringInfoString(state, "FETCH ");
+
+ switch (fetch_stmt->direction)
+ {
+ case FETCH_FORWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ // Default
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ deparseAppendStringInfoString(state, "ALL ");
+ }
+ else
+ {
+ deparseAppendStringInfo(state, "FORWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_BACKWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ deparseAppendStringInfoString(state, "PRIOR ");
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ deparseAppendStringInfoString(state, "BACKWARD ALL ");
+ }
+ else
+ {
+ deparseAppendStringInfo(state, "BACKWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_ABSOLUTE:
+ if (fetch_stmt->howMany == 1)
+ {
+ deparseAppendStringInfoString(state, "FIRST ");
+ }
+ else if (fetch_stmt->howMany == -1)
+ {
+ deparseAppendStringInfoString(state, "LAST ");
+ }
+ else
+ {
+ deparseAppendStringInfo(state, "ABSOLUTE %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_RELATIVE:
+ deparseAppendStringInfo(state, "RELATIVE %ld ", fetch_stmt->howMany);
+ }
+
+ deparseAppendStringInfoString(state, quote_identifier(fetch_stmt->portalname));
+}
+
+static void deparseAlterDefaultPrivilegesStmt(DeparseState *state, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER DEFAULT PRIVILEGES ");
+
+ foreach (lc, alter_default_privileges_stmt->options)
+ {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp(defelem->defname, "schemas") == 0)
+ {
+ deparseAppendStringInfoString(state, "IN SCHEMA ");
+ deparseNameList(state, castNode(List, defelem->arg));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (strcmp(defelem->defname, "roles") == 0)
+ {
+ deparseAppendStringInfoString(state, "FOR ROLE ");
+ deparseRoleList(state, castNode(List, defelem->arg));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ // No other DefElems are supported
+ Assert(false);
+ }
+ }
+
+ deparseGrantStmt(state, alter_default_privileges_stmt->action);
+}
+
+static void deparseReindexStmt(DeparseState *state, ReindexStmt *reindex_stmt)
+{
+ deparseAppendStringInfoString(state, "REINDEX ");
+
+ deparseUtilityOptionList(state, reindex_stmt->params);
+
+ switch (reindex_stmt->kind)
+ {
+ case REINDEX_OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case REINDEX_OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case REINDEX_OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case REINDEX_OBJECT_SYSTEM:
+ deparseAppendStringInfoString(state, "SYSTEM ");
+ break;
+ case REINDEX_OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ break;
+ }
+
+ if (reindex_stmt->relation != NULL)
+ {
+ deparseRangeVar(state, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (reindex_stmt->name != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(reindex_stmt->name));
+ }
+}
+
+static void deparseRuleStmt(DeparseState *state, RuleStmt* rule_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (rule_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ deparseAppendStringInfoString(state, "RULE ");
+ deparseAppendStringInfoString(state, quote_identifier(rule_stmt->rulename));
+ deparseAppendStringInfoString(state, " AS ON ");
+
+ switch (rule_stmt->event)
+ {
+ case CMD_UNKNOWN:
+ case CMD_UTILITY:
+ case CMD_NOTHING:
+ // Not supported here
+ Assert(false);
+ break;
+ case CMD_SELECT:
+ deparseAppendStringInfoString(state, "SELECT ");
+ break;
+ case CMD_UPDATE:
+ deparseAppendStringInfoString(state, "UPDATE ");
+ break;
+ case CMD_INSERT:
+ deparseAppendStringInfoString(state, "INSERT ");
+ break;
+ case CMD_DELETE:
+ deparseAppendStringInfoString(state, "DELETE ");
+ break;
+ case CMD_MERGE:
+ deparseAppendStringInfoString(state, "MERGE ");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "TO ");
+ deparseRangeVar(state, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseWhereClause(state, rule_stmt->whereClause);
+
+ deparseAppendStringInfoString(state, "DO ");
+
+ if (rule_stmt->instead)
+ deparseAppendStringInfoString(state, "INSTEAD ");
+
+ if (list_length(rule_stmt->actions) == 0)
+ {
+ deparseAppendStringInfoString(state, "NOTHING");
+ }
+ else if (list_length(rule_stmt->actions) == 1)
+ {
+ deparseRuleActionStmt(state, linitial(rule_stmt->actions));
+ }
+ else
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach (lc, rule_stmt->actions)
+ {
+ deparseRuleActionStmt(state, lfirst(lc));
+ if (lnext(rule_stmt->actions, lc))
+ deparseAppendStringInfoString(state, "; ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+static void deparseNotifyStmt(DeparseState *state, NotifyStmt *notify_stmt)
+{
+ deparseAppendStringInfoString(state, "NOTIFY ");
+ deparseAppendStringInfoString(state, quote_identifier(notify_stmt->conditionname));
+
+ if (notify_stmt->payload != NULL)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ deparseStringLiteral(state, notify_stmt->payload);
+ }
+}
+
+static void deparseListenStmt(DeparseState *state, ListenStmt *listen_stmt)
+{
+ deparseAppendStringInfoString(state, "LISTEN ");
+ deparseAppendStringInfoString(state, quote_identifier(listen_stmt->conditionname));
+}
+
+static void deparseUnlistenStmt(DeparseState *state, UnlistenStmt *unlisten_stmt)
+{
+ deparseAppendStringInfoString(state, "UNLISTEN ");
+ if (unlisten_stmt->conditionname == NULL)
+ deparseAppendStringInfoString(state, "*");
+ else
+ deparseAppendStringInfoString(state, quote_identifier(unlisten_stmt->conditionname));
+}
+
+static void deparseCreateSeqStmt(DeparseState *state, CreateSeqStmt *create_seq_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ deparseOptTemp(state, create_seq_stmt->sequence->relpersistence);
+
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+
+ if (create_seq_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseRangeVar(state, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseOptSeqOptList(state, create_seq_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterFunctionStmt(DeparseState *state, AlterFunctionStmt *alter_function_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (alter_function_stmt->objtype)
+ {
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ deparseFunctionWithArgtypes(state, alter_function_stmt->func);
+ deparseAppendStringInfoChar(state, ' ');
+
+ foreach (lc, alter_function_stmt->actions)
+ {
+ deparseCommonFuncOptItem(state, castNode(DefElem, lfirst(lc)));
+ if (lnext(alter_function_stmt->actions, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+static void deparseTruncateStmt(DeparseState *state, TruncateStmt *truncate_stmt)
+{
+ deparseAppendStringInfoString(state, "TRUNCATE ");
+
+ deparseRelationExprList(state, truncate_stmt->relations);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (truncate_stmt->restart_seqs)
+ deparseAppendStringInfoString(state, "RESTART IDENTITY ");
+
+ deparseOptDropBehavior(state, truncate_stmt->behavior);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateEventTrigStmt(DeparseState *state, CreateEventTrigStmt *create_event_trig_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE EVENT TRIGGER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_event_trig_stmt->trigname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "ON ");
+ deparseAppendStringInfoString(state, quote_identifier(create_event_trig_stmt->eventname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_event_trig_stmt->whenclause)
+ {
+ deparseAppendStringInfoString(state, "WHEN ");
+
+ foreach (lc, create_event_trig_stmt->whenclause)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ List *l = castNode(List, def_elem->arg);
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoString(state, " IN (");
+ foreach (lc2, l)
+ {
+ deparseStringLiteral(state, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ if (lnext(create_event_trig_stmt->whenclause, lc))
+ deparseAppendStringInfoString(state, " AND ");
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "EXECUTE FUNCTION ");
+ deparseFuncName(state, create_event_trig_stmt->funcname);
+ deparseAppendStringInfoString(state, "()");
+}
+
+static void deparseAlterEventTrigStmt(DeparseState *state, AlterEventTrigStmt *alter_event_trig_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER EVENT TRIGGER ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_event_trig_stmt->trigname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (alter_event_trig_stmt->tgenabled)
+ {
+ case TRIGGER_FIRES_ON_ORIGIN:
+ deparseAppendStringInfoString(state, "ENABLE");
+ break;
+ case TRIGGER_FIRES_ON_REPLICA:
+ deparseAppendStringInfoString(state, "ENABLE REPLICA");
+ break;
+ case TRIGGER_FIRES_ALWAYS:
+ deparseAppendStringInfoString(state, "ENABLE ALWAYS");
+ break;
+ case TRIGGER_DISABLED:
+ deparseAppendStringInfoString(state, "DISABLE");
+ break;
+ }
+}
+
+static void deparseRefreshMatViewStmt(DeparseState *state, RefreshMatViewStmt *refresh_mat_view_stmt)
+{
+ deparseAppendStringInfoString(state, "REFRESH MATERIALIZED VIEW ");
+
+ if (refresh_mat_view_stmt->concurrent)
+ deparseAppendStringInfoString(state, "CONCURRENTLY ");
+
+ deparseRangeVar(state, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (refresh_mat_view_stmt->skipData)
+ deparseAppendStringInfoString(state, "WITH NO DATA ");
+
+ removeTrailingSpace(state);
+}
+
+static void deparseReplicaIdentityStmt(DeparseState *state, ReplicaIdentityStmt *replica_identity_stmt)
+{
+ switch (replica_identity_stmt->identity_type)
+ {
+ case REPLICA_IDENTITY_NOTHING:
+ deparseAppendStringInfoString(state, "NOTHING ");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ deparseAppendStringInfoString(state, "FULL ");
+ break;
+ case REPLICA_IDENTITY_DEFAULT:
+ deparseAppendStringInfoString(state, "DEFAULT ");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ Assert(replica_identity_stmt->name != NULL);
+ deparseAppendStringInfoString(state, "USING INDEX ");
+ deparseAppendStringInfoString(state, quote_identifier(replica_identity_stmt->name));
+ break;
+ }
+}
+
+// "CreatePolicyStmt" in gram.y
+static void deparseCreatePolicyStmt(DeparseState *state, CreatePolicyStmt *create_policy_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE POLICY ");
+ deparseColId(state, create_policy_stmt->policy_name);
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (!create_policy_stmt->permissive)
+ deparseAppendStringInfoString(state, "AS RESTRICTIVE ");
+
+ if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
+ Assert(true); // Default
+ else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
+ deparseAppendStringInfoString(state, "FOR SELECT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
+ deparseAppendStringInfoString(state, "FOR INSERT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
+ deparseAppendStringInfoString(state, "FOR UPDATE ");
+ else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
+ deparseAppendStringInfoString(state, "FOR DELETE ");
+ else
+ Assert(false);
+
+ deparseAppendStringInfoString(state, "TO ");
+ deparseRoleList(state, create_policy_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_policy_stmt->qual != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING (");
+ deparseExpr(state, create_policy_stmt->qual, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (create_policy_stmt->with_check != NULL)
+ {
+ deparseAppendStringInfoString(state, "WITH CHECK (");
+ deparseExpr(state, create_policy_stmt->with_check, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+}
+
+// "AlterPolicyStmt" in gram.y
+static void deparseAlterPolicyStmt(DeparseState *state, AlterPolicyStmt *alter_policy_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER POLICY ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_policy_stmt->policy_name));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(alter_policy_stmt->roles) > 0)
+ {
+ deparseAppendStringInfoString(state, "TO ");
+ deparseRoleList(state, alter_policy_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (alter_policy_stmt->qual != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING (");
+ deparseExpr(state, alter_policy_stmt->qual, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (alter_policy_stmt->with_check != NULL)
+ {
+ deparseAppendStringInfoString(state, "WITH CHECK (");
+ deparseExpr(state, alter_policy_stmt->with_check, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+}
+
+static void deparseCreateTableSpaceStmt(DeparseState *state, CreateTableSpaceStmt *create_table_space_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE TABLESPACE ");
+ deparseColId(state, create_table_space_stmt->tablespacename);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_table_space_stmt->owner != NULL)
+ {
+ deparseAppendStringInfoString(state, "OWNER ");
+ deparseRoleSpec(state, create_table_space_stmt->owner);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "LOCATION ");
+
+ if (create_table_space_stmt->location != NULL)
+ deparseStringLiteral(state, create_table_space_stmt->location);
+ else
+ deparseAppendStringInfoString(state, "''");
+
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseOptWith(state, create_table_space_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateTransformStmt(DeparseState *state, CreateTransformStmt *create_transform_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE ");
+ if (create_transform_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ deparseAppendStringInfoString(state, "TRANSFORM FOR ");
+ deparseTypeName(state, create_transform_stmt->type_name);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseAppendStringInfoString(state, quote_identifier(create_transform_stmt->lang));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoChar(state, '(');
+
+ if (create_transform_stmt->fromsql)
+ {
+ deparseAppendStringInfoString(state, "FROM SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(state, create_transform_stmt->fromsql);
+ }
+
+ if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
+ deparseAppendStringInfoString(state, ", ");
+
+ if (create_transform_stmt->tosql)
+ {
+ deparseAppendStringInfoString(state, "TO SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(state, create_transform_stmt->tosql);
+ }
+
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseCreateAmStmt(DeparseState *state, CreateAmStmt *create_am_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE ACCESS METHOD ");
+ deparseAppendStringInfoString(state, quote_identifier(create_am_stmt->amname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "TYPE ");
+ switch (create_am_stmt->amtype)
+ {
+ case AMTYPE_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case AMTYPE_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "HANDLER ");
+ deparseHandlerName(state, create_am_stmt->handler_name);
+}
+
+// "pub_obj_list" in gram.y
+static void deparsePublicationObjectList(DeparseState *state, List *pubobjects) {
+ const ListCell *lc;
+ foreach(lc, pubobjects) {
+ PublicationObjSpec *obj = lfirst(lc);
+
+ switch (obj->pubobjtype) {
+ case PUBLICATIONOBJ_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ deparseRangeVar(state, obj->pubtable->relation, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (obj->pubtable->columns)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, obj->pubtable->columns);
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ if (obj->pubtable->whereClause)
+ {
+ deparseAppendStringInfoString(state, " WHERE (");
+ deparseExpr(state, obj->pubtable->whereClause, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ")");
+ }
+
+ break;
+ case PUBLICATIONOBJ_TABLES_IN_SCHEMA:
+ deparseAppendStringInfoString(state, "TABLES IN SCHEMA ");
+ deparseAppendStringInfoString(state, quote_identifier(obj->name));
+ break;
+ case PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA:
+ deparseAppendStringInfoString(state, "TABLES IN SCHEMA CURRENT_SCHEMA");
+ break;
+ case PUBLICATIONOBJ_CONTINUATION:
+ // This should be unreachable, the parser merges these before we can even get here.
+ Assert(false);
+ break;
+ }
+
+ if (lnext(pubobjects, lc)) {
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+}
+
+static void deparseCreatePublicationStmt(DeparseState *state, CreatePublicationStmt *create_publication_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE PUBLICATION ");
+ deparseAppendStringInfoString(state, quote_identifier(create_publication_stmt->pubname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(create_publication_stmt->pubobjects) > 0)
+ {
+ deparseAppendStringInfoString(state, "FOR ");
+ deparsePublicationObjectList(state, create_publication_stmt->pubobjects);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (create_publication_stmt->for_all_tables)
+ {
+ deparseAppendStringInfoString(state, "FOR ALL TABLES ");
+ }
+
+ deparseOptDefinition(state, create_publication_stmt->options);
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterPublicationStmt(DeparseState *state, AlterPublicationStmt *alter_publication_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER PUBLICATION ");
+ deparseColId(state, alter_publication_stmt->pubname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(alter_publication_stmt->pubobjects) > 0)
+ {
+ switch (alter_publication_stmt->action)
+ {
+ case AP_SetObjects:
+ deparseAppendStringInfoString(state, "SET ");
+ break;
+ case AP_AddObjects:
+ deparseAppendStringInfoString(state, "ADD ");
+ break;
+ case AP_DropObjects:
+ deparseAppendStringInfoString(state, "DROP ");
+ break;
+ }
+
+ deparsePublicationObjectList(state, alter_publication_stmt->pubobjects);
+ }
+ else if (list_length(alter_publication_stmt->options) > 0)
+ {
+ deparseAppendStringInfoString(state, "SET ");
+ deparseDefinition(state, alter_publication_stmt->options);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+static void deparseAlterSeqStmt(DeparseState *state, AlterSeqStmt *alter_seq_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER SEQUENCE ");
+
+ if (alter_seq_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseRangeVar(state, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseSeqOptList(state, alter_seq_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterSystemStmt(DeparseState *state, AlterSystemStmt *alter_system_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER SYSTEM ");
+ deparseVariableSetStmt(state, alter_system_stmt->setstmt);
+}
+
+static void deparseCommentStmt(DeparseState *state, CommentStmt *comment_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ deparseAppendStringInfoString(state, "COMMENT ON ");
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ deparseAppendStringInfoString(state, "COLUMN ");
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_ACCESS_METHOD:
+ deparseAppendStringInfoString(state, "ACCESS METHOD ");
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ deparseAppendStringInfoString(state, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ break;
+ case OBJECT_ROLE:
+ deparseAppendStringInfoString(state, "ROLE ");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseAppendStringInfoString(state, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ break;
+ case OBJECT_POLICY:
+ deparseAppendStringInfoString(state, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ deparseAppendStringInfoString(state, "RULE ");
+ break;
+ case OBJECT_TRANSFORM:
+ deparseAppendStringInfoString(state, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, "TRIGGER ");
+ break;
+ case OBJECT_OPCLASS:
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECT ");
+ break;
+ case OBJECT_CAST:
+ deparseAppendStringInfoString(state, "CAST ");
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ deparseAnyName(state, castNode(List, comment_stmt->object));
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, quote_identifier(strVal(comment_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ deparseTypeName(state, castNode(TypeName, comment_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ l = castNode(List, comment_stmt->object);
+ deparseAppendStringInfoString(state, quote_identifier(strVal(llast(l))));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseAnyNameSkipLast(state, l);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ l = castNode(List, comment_stmt->object);
+ deparseAppendStringInfoString(state, quote_identifier(strVal(llast(l))));
+ deparseAppendStringInfoString(state, " ON DOMAIN ");
+ deparseTypeName(state, linitial(l));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, comment_stmt->object);
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " LANGUAGE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lsecond(l))));
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, comment_stmt->object);
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseValue(state, (union ValUnion *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, comment_stmt->object);
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, castNode(TypeName, lsecond(l)));
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, " IS ");
+
+ if (comment_stmt->comment != NULL)
+ deparseStringLiteral(state, comment_stmt->comment);
+ else
+ deparseAppendStringInfoString(state, "NULL");
+}
+
+// "stats_param" in gram.y
+static void deparseStatsElem(DeparseState *state, StatsElem *stats_elem)
+{
+ // only one of stats_elem->name or stats_elem->expr can be non-null
+ if (stats_elem->name)
+ deparseAppendStringInfoString(state, stats_elem->name);
+ else if (stats_elem->expr)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, stats_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+static void deparseCreateStatsStmt(DeparseState *state, CreateStatsStmt *create_stats_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE STATISTICS ");
+
+ if (create_stats_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseAnyName(state, create_stats_stmt->defnames);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(create_stats_stmt->stat_types) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseNameList(state, create_stats_stmt->stat_types);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseAppendStringInfoString(state, "ON ");
+ foreach (lc, create_stats_stmt->exprs)
+ {
+ deparseStatsElem(state, lfirst(lc));
+ if (lnext(create_stats_stmt->exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseFromList(state, create_stats_stmt->relations);
+}
+
+static void deparseAlterCollationStmt(DeparseState *state, AlterCollationStmt *alter_collation_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER COLLATION ");
+ deparseAnyName(state, alter_collation_stmt->collname);
+ deparseAppendStringInfoString(state, " REFRESH VERSION");
+}
+
+static void deparseAlterDatabaseStmt(DeparseState *state, AlterDatabaseStmt *alter_database_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER DATABASE ");
+ deparseColId(state, alter_database_stmt->dbname);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseCreatedbOptList(state, alter_database_stmt->options);
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterDatabaseSetStmt(DeparseState *state, AlterDatabaseSetStmt *alter_database_set_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER DATABASE ");
+ deparseColId(state, alter_database_set_stmt->dbname);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseVariableSetStmt(state, alter_database_set_stmt->setstmt);
+}
+
+static void deparseAlterStatsStmt(DeparseState *state, AlterStatsStmt *alter_stats_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER STATISTICS ");
+
+ if (alter_stats_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAnyName(state, alter_stats_stmt->defnames);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_stats_stmt->stxstattarget)
+ deparseAppendStringInfo(state, "SET STATISTICS %d", castNode(Integer, alter_stats_stmt->stxstattarget)->ival);
+ else
+ deparseAppendStringInfo(state, "SET STATISTICS DEFAULT");
+}
+
+static void deparseAlterTSDictionaryStmt(DeparseState *state, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER TEXT SEARCH DICTIONARY ");
+
+ deparseAnyName(state, alter_ts_dictionary_stmt->dictname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseDefinition(state, alter_ts_dictionary_stmt->options);
+}
+
+static void deparseAlterTSConfigurationStmt(DeparseState *state, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(state, alter_ts_configuration_stmt->cfgname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (alter_ts_configuration_stmt->kind)
+ {
+ case ALTER_TSCONFIG_ADD_MAPPING:
+ deparseAppendStringInfoString(state, "ADD MAPPING FOR ");
+ deparseNameList(state, alter_ts_configuration_stmt->tokentype);
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyNameList(state, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+ deparseAppendStringInfoString(state, "ALTER MAPPING FOR ");
+ deparseNameList(state, alter_ts_configuration_stmt->tokentype);
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyNameList(state, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT:
+ deparseAppendStringInfoString(state, "ALTER MAPPING REPLACE ");
+ deparseAnyName(state, linitial(alter_ts_configuration_stmt->dicts));
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyName(state, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+ deparseAppendStringInfoString(state, "ALTER MAPPING FOR ");
+ deparseNameList(state, alter_ts_configuration_stmt->tokentype);
+ deparseAppendStringInfoString(state, " REPLACE ");
+ deparseAnyName(state, linitial(alter_ts_configuration_stmt->dicts));
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyName(state, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_DROP_MAPPING:
+ deparseAppendStringInfoString(state, "DROP MAPPING ");
+ if (alter_ts_configuration_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseNameList(state, alter_ts_configuration_stmt->tokentype);
+ break;
+ }
+}
+
+static void deparseVariableShowStmt(DeparseState *state, VariableShowStmt *variable_show_stmt)
+{
+ deparseAppendStringInfoString(state, "SHOW ");
+
+ if (strcmp(variable_show_stmt->name, "timezone") == 0)
+ deparseAppendStringInfoString(state, "TIME ZONE");
+ else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
+ deparseAppendStringInfoString(state, "TRANSACTION ISOLATION LEVEL");
+ else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
+ deparseAppendStringInfoString(state, "SESSION AUTHORIZATION");
+ else if (strcmp(variable_show_stmt->name, "all") == 0)
+ deparseAppendStringInfoString(state, "ALL");
+ else
+ deparseAppendStringInfoString(state, quote_identifier(variable_show_stmt->name));
+}
+
+// "tablesample_clause" in gram.y
+static void deparseRangeTableSample(DeparseState *state, RangeTableSample *range_table_sample)
+{
+ deparseRangeVar(state, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
+
+ deparseAppendStringInfoString(state, " TABLESAMPLE ");
+
+ deparseFuncName(state, range_table_sample->method);
+ deparseAppendStringInfoChar(state, '(');
+ deparseExprList(state, range_table_sample->args);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (range_table_sample->repeatable != NULL)
+ {
+ deparseAppendStringInfoString(state, "REPEATABLE (");
+ deparseExpr(state, range_table_sample->repeatable, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateSubscriptionStmt(DeparseState *state, CreateSubscriptionStmt *create_subscription_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE SUBSCRIPTION ");
+ deparseAppendStringInfoString(state, quote_identifier(create_subscription_stmt->subname));
+
+ deparseAppendStringInfoString(state, " CONNECTION ");
+ if (create_subscription_stmt->conninfo != NULL)
+ deparseStringLiteral(state, create_subscription_stmt->conninfo);
+ else
+ deparseAppendStringInfoString(state, "''");
+
+ deparseAppendStringInfoString(state, " PUBLICATION ");
+
+ foreach(lc, create_subscription_stmt->publication)
+ {
+ deparseColLabel(state, strVal(lfirst(lc)));
+ if (lnext(create_subscription_stmt->publication, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseOptDefinition(state, create_subscription_stmt->options);
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterSubscriptionStmt(DeparseState *state, AlterSubscriptionStmt *alter_subscription_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER SUBSCRIPTION ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_subscription_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (alter_subscription_stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ deparseAppendStringInfoString(state, "SET ");
+ deparseDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SKIP:
+ deparseAppendStringInfoString(state, "SKIP ");
+ deparseDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ deparseAppendStringInfoString(state, "CONNECTION ");
+ deparseStringLiteral(state, alter_subscription_stmt->conninfo);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case ALTER_SUBSCRIPTION_REFRESH:
+ deparseAppendStringInfoString(state, "REFRESH PUBLICATION ");
+ deparseOptDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ADD_PUBLICATION:
+ deparseAppendStringInfoString(state, "ADD PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(state, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ deparseOptDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_DROP_PUBLICATION:
+ deparseAppendStringInfoString(state, "DROP PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(state, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ deparseOptDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SET_PUBLICATION:
+ deparseAppendStringInfoString(state, "SET PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(state, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ deparseOptDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ENABLED:
+ Assert(list_length(alter_subscription_stmt->options) == 1);
+ DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
+ Assert(strcmp(defelem->defname, "enabled") == 0);
+ if (optBooleanValue(defelem->arg))
+ {
+ deparseAppendStringInfoString(state, " ENABLE ");
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, " DISABLE ");
+ }
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDropSubscriptionStmt(DeparseState *state, DropSubscriptionStmt *drop_subscription_stmt)
+{
+ deparseAppendStringInfoString(state, "DROP SUBSCRIPTION ");
+
+ if (drop_subscription_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAppendStringInfoString(state, drop_subscription_stmt->subname);
+}
+
+static void deparseCallStmt(DeparseState *state, CallStmt *call_stmt)
+{
+ deparseAppendStringInfoString(state, "CALL ");
+ deparseFuncCall(state, call_stmt->funccall, DEPARSE_NODE_CONTEXT_NONE);
+}
+
+static void deparseAlterOwnerStmt(DeparseState *state, AlterOwnerStmt *alter_owner_stmt)
+{
+ List *l = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (alter_owner_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECT ");
+ deparseNumericOnly(state, (union ValUnion *) alter_owner_stmt->object);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_owner_stmt->object);
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseColId(state, strVal(linitial(l)));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_owner_stmt->object);
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseColId(state, strVal(linitial(l)));
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseAppendStringInfoString(state, "SUBSCRIPTION ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseAppendStringInfoString(state, " OWNER TO ");
+ deparseRoleSpec(state, alter_owner_stmt->newowner);
+}
+
+// "operator_def_list" in gram.y
+static void deparseOperatorDefList(DeparseState *state, List *defs)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, defs)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoString(state, " = ");
+ if (def_elem->arg != NULL)
+ deparseDefArg(state, def_elem->arg, true);
+ else
+ deparseAppendStringInfoString(state, "NONE");
+
+ if (lnext(defs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+static void deparseAlterOperatorStmt(DeparseState *state, AlterOperatorStmt *alter_operator_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER OPERATOR ");
+ deparseOperatorWithArgtypes(state, alter_operator_stmt->opername);
+ deparseAppendStringInfoString(state, " SET (");
+ deparseOperatorDefList(state, alter_operator_stmt->options);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseAlterTypeStmt(DeparseState *state, AlterTypeStmt *alter_type_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER TYPE ");
+ deparseAnyName(state, alter_type_stmt->typeName);
+ deparseAppendStringInfoString(state, " SET (");
+ deparseOperatorDefList(state, alter_type_stmt->options);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseDropOwnedStmt(DeparseState *state, DropOwnedStmt *drop_owned_stmt)
+{
+ deparseAppendStringInfoString(state, "DROP OWNED BY ");
+ deparseRoleList(state, drop_owned_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseOptDropBehavior(state, drop_owned_stmt->behavior);
+ removeTrailingSpace(state);
+}
+
+static void deparseReassignOwnedStmt(DeparseState *state, ReassignOwnedStmt *reassigned_owned_stmt)
+{
+ deparseAppendStringInfoString(state, "REASSIGN OWNED BY ");
+
+ deparseRoleList(state, reassigned_owned_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "TO ");
+ deparseRoleSpec(state, reassigned_owned_stmt->newrole);
+}
+
+static void deparseClosePortalStmt(DeparseState *state, ClosePortalStmt *close_portal_stmt)
+{
+ deparseAppendStringInfoString(state, "CLOSE ");
+ if (close_portal_stmt->portalname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(close_portal_stmt->portalname));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ALL");
+ }
+}
+
+// "CreateTrigStmt" in gram.y
+static void deparseCreateTrigStmt(DeparseState *state, CreateTrigStmt *create_trig_stmt)
+{
+ ListCell *lc;
+ bool skip_events_or = true;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+ if (create_trig_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+ if (create_trig_stmt->isconstraint)
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ deparseAppendStringInfoString(state, "TRIGGER ");
+
+ deparseAppendStringInfoString(state, quote_identifier(create_trig_stmt->trigname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (create_trig_stmt->timing)
+ {
+ case TRIGGER_TYPE_BEFORE:
+ deparseAppendStringInfoString(state, "BEFORE ");
+ break;
+ case TRIGGER_TYPE_AFTER:
+ deparseAppendStringInfoString(state, "AFTER ");
+ break;
+ case TRIGGER_TYPE_INSTEAD:
+ deparseAppendStringInfoString(state, "INSTEAD OF ");
+ break;
+ default:
+ Assert(false);
+ }
+
+ if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
+ {
+ deparseAppendStringInfoString(state, "INSERT ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ deparseAppendStringInfoString(state, "OR ");
+ deparseAppendStringInfoString(state, "DELETE ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ deparseAppendStringInfoString(state, "OR ");
+ deparseAppendStringInfoString(state, "UPDATE ");
+ if (list_length(create_trig_stmt->columns) > 0)
+ {
+ deparseAppendStringInfoString(state, "OF ");
+ deparseColumnList(state, create_trig_stmt->columns);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ deparseAppendStringInfoString(state, "OR ");
+ deparseAppendStringInfoString(state, "TRUNCATE ");
+ }
+
+ deparseAppendStringInfoString(state, "ON ");
+ deparseRangeVar(state, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_trig_stmt->transitionRels != NULL)
+ {
+ deparseAppendStringInfoString(state, "REFERENCING ");
+ foreach(lc, create_trig_stmt->transitionRels)
+ {
+ deparseTriggerTransition(state, castNode(TriggerTransition, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ if (create_trig_stmt->constrrel != NULL)
+ {
+ deparseAppendStringInfoString(state, "FROM ");
+ deparseRangeVar(state, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_trig_stmt->deferrable)
+ deparseAppendStringInfoString(state, "DEFERRABLE ");
+
+ if (create_trig_stmt->initdeferred)
+ deparseAppendStringInfoString(state, "INITIALLY DEFERRED ");
+
+ if (create_trig_stmt->row)
+ deparseAppendStringInfoString(state, "FOR EACH ROW ");
+
+ if (create_trig_stmt->whenClause)
+ {
+ deparseAppendStringInfoString(state, "WHEN (");
+ deparseExpr(state, create_trig_stmt->whenClause, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseAppendStringInfoString(state, "EXECUTE FUNCTION ");
+ deparseFuncName(state, create_trig_stmt->funcname);
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, create_trig_stmt->args)
+ {
+ deparseStringLiteral(state, strVal(lfirst(lc)));
+ if (lnext(create_trig_stmt->args, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseTriggerTransition(DeparseState *state, TriggerTransition *trigger_transition)
+{
+ if (trigger_transition->isNew)
+ deparseAppendStringInfoString(state, "NEW ");
+ else
+ deparseAppendStringInfoString(state, "OLD ");
+
+ if (trigger_transition->isTable)
+ deparseAppendStringInfoString(state, "TABLE ");
+ else
+ deparseAppendStringInfoString(state, "ROW ");
+
+ deparseAppendStringInfoString(state, quote_identifier(trigger_transition->name));
+}
+
+static void deparseXmlExpr(DeparseState *state, XmlExpr* xml_expr, DeparseNodeContext context)
+{
+ switch (xml_expr->op)
+ {
+ case IS_XMLCONCAT: /* XMLCONCAT(args) */
+ deparseAppendStringInfoString(state, "xmlconcat(");
+ deparseExprList(state, xml_expr->args);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
+ deparseAppendStringInfoString(state, "xmlelement(name ");
+ deparseAppendStringInfoString(state, quote_identifier(xml_expr->name));
+ if (xml_expr->named_args != NULL)
+ {
+ deparseAppendStringInfoString(state, ", xmlattributes(");
+ deparseXmlAttributeList(state, xml_expr->named_args);
+ deparseAppendStringInfoString(state, ")");
+ }
+ if (xml_expr->args != NULL)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ deparseExprList(state, xml_expr->args);
+ }
+ deparseAppendStringInfoString(state, ")");
+ break;
+ case IS_XMLFOREST: /* XMLFOREST(xml_attributes) */
+ deparseAppendStringInfoString(state, "xmlforest(");
+ deparseXmlAttributeList(state, xml_expr->named_args);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
+ Assert(list_length(xml_expr->args) == 2);
+ deparseAppendStringInfoString(state, "xmlparse(");
+ switch (xml_expr->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ deparseAppendStringInfoString(state, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ deparseAppendStringInfoString(state, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(state, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLPI: /* XMLPI(name [, args]) */
+ deparseAppendStringInfoString(state, "xmlpi(name ");
+ deparseAppendStringInfoString(state, quote_identifier(xml_expr->name));
+ if (xml_expr->args != NULL)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
+ deparseAppendStringInfoString(state, "xmlroot(");
+ deparseExpr(state, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ", version ");
+ if (castNode(A_Const, lsecond(xml_expr->args))->isnull)
+ deparseAppendStringInfoString(state, "no value");
+ else
+ deparseExpr(state, lsecond(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
+ deparseAppendStringInfoString(state, ", standalone yes");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
+ deparseAppendStringInfoString(state, ", standalone no");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
+ deparseAppendStringInfoString(state, ", standalone no value");
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLSERIALIZE: /* XMLSERIALIZE(is_document, xmlval) */
+ // These are represented as XmlSerialize in raw parse trees
+ Assert(false);
+ break;
+ case IS_DOCUMENT: /* xmlval IS DOCUMENT */
+ Assert(list_length(xml_expr->args) == 1);
+ deparseExpr(state, linitial(xml_expr->args), context);
+ deparseAppendStringInfoString(state, " IS DOCUMENT");
+ break;
+ }
+}
+
+// "xmltable_column_el" in gram.y
+static void deparseRangeTableFuncCol(DeparseState *state, RangeTableFuncCol* range_table_func_col)
+{
+ deparseAppendStringInfoString(state, quote_identifier(range_table_func_col->colname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (range_table_func_col->for_ordinality)
+ {
+ deparseAppendStringInfoString(state, "FOR ORDINALITY ");
+ }
+ else
+ {
+ deparseTypeName(state, range_table_func_col->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (range_table_func_col->colexpr)
+ {
+ deparseAppendStringInfoString(state, "PATH ");
+ deparseExpr(state, range_table_func_col->colexpr, DEPARSE_NODE_CONTEXT_NONE /* b_expr */);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (range_table_func_col->coldefexpr)
+ {
+ deparseAppendStringInfoString(state, "DEFAULT ");
+ deparseExpr(state, range_table_func_col->coldefexpr, DEPARSE_NODE_CONTEXT_NONE /* b_expr */);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (range_table_func_col->is_not_null)
+ deparseAppendStringInfoString(state, "NOT NULL ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "table_ref" and "xmltable" in gram.y
+static void deparseRangeTableFunc(DeparseState *state, RangeTableFunc* range_table_func)
+{
+ ListCell *lc;
+
+ if (range_table_func->lateral)
+ deparseAppendStringInfoString(state, "LATERAL ");
+
+ deparseAppendStringInfoString(state, "xmltable(");
+ if (range_table_func->namespaces)
+ {
+ deparseAppendStringInfoString(state, "xmlnamespaces(");
+ deparseXmlNamespaceList(state, range_table_func->namespaces);
+ deparseAppendStringInfoString(state, "), ");
+ }
+
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, range_table_func->rowexpr, DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+ deparseAppendStringInfoChar(state, ')');
+
+ deparseAppendStringInfoString(state, " PASSING ");
+ deparseExpr(state, range_table_func->docexpr, DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+
+ deparseAppendStringInfoString(state, " COLUMNS ");
+ foreach(lc, range_table_func->columns)
+ {
+ deparseRangeTableFuncCol(state, castNode(RangeTableFuncCol, lfirst(lc)));
+ if (lnext(range_table_func->columns, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseAppendStringInfoString(state, ") ");
+
+ if (range_table_func->alias)
+ {
+ deparseAppendStringInfoString(state, "AS ");
+ deparseAlias(state, range_table_func->alias);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseXmlSerialize(DeparseState *state, XmlSerialize *xml_serialize)
+{
+ deparseAppendStringInfoString(state, "xmlserialize(");
+ switch (xml_serialize->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ deparseAppendStringInfoString(state, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ deparseAppendStringInfoString(state, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(state, xml_serialize->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, xml_serialize->typeName);
+
+ if (xml_serialize->indent) {
+ deparseAppendStringInfoString(state, " INDENT");
+ }
+
+ deparseAppendStringInfoString(state, ")");
+}
+
+static void deparseJsonFormat(DeparseState *state, JsonFormat *json_format)
+{
+ if (json_format == NULL || json_format->format_type == JS_FORMAT_DEFAULT)
+ return;
+
+ deparseAppendStringInfoString(state, "FORMAT JSON ");
+
+ switch (json_format->encoding)
+ {
+ case JS_ENC_UTF8:
+ deparseAppendStringInfoString(state, "ENCODING utf8 ");
+ break;
+ case JS_ENC_UTF16:
+ deparseAppendStringInfoString(state, "ENCODING utf16 ");
+ break;
+ case JS_ENC_UTF32:
+ deparseAppendStringInfoString(state, "ENCODING utf32 ");
+ break;
+ case JS_ENC_DEFAULT:
+ // no encoding specified
+ break;
+ }
+}
+
+static void deparseJsonIsPredicate(DeparseState *state, JsonIsPredicate *j)
+{
+ deparseExpr(state, j->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseJsonFormat(state, castNode(JsonFormat, j->format));
+
+ deparseAppendStringInfoString(state, "IS ");
+
+ switch (j->item_type)
+ {
+ case JS_TYPE_ANY:
+ deparseAppendStringInfoString(state, "JSON ");
+ break;
+ case JS_TYPE_ARRAY:
+ deparseAppendStringInfoString(state, "JSON ARRAY ");
+ break;
+ case JS_TYPE_OBJECT:
+ deparseAppendStringInfoString(state, "JSON OBJECT ");
+ break;
+ case JS_TYPE_SCALAR:
+ deparseAppendStringInfoString(state, "JSON SCALAR ");
+ break;
+ }
+
+ if (j->unique_keys)
+ deparseAppendStringInfoString(state, "WITH UNIQUE ");
+
+ removeTrailingSpace(state);
+}
+
+// "json_value_expr" in gram.y
+static void deparseJsonValueExpr(DeparseState *state, JsonValueExpr *json_value_expr)
+{
+ deparseExpr(state, (Node *) json_value_expr->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonFormat(state, json_value_expr->format);
+}
+
+// "json_value_expr_list" in gram.y
+static void deparseJsonValueExprList(DeparseState *state, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseJsonValueExpr(state, lfirst(lc));
+ removeTrailingSpace(state);
+ if (lnext(exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+}
+
+// "json_name_and_value" in gram.y
+static void deparseJsonKeyValue(DeparseState *state, JsonKeyValue *json_key_value)
+{
+ deparseExpr(state, (Node *) json_key_value->key, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ": ");
+ deparseJsonValueExpr(state, json_key_value->value);
+}
+
+// "json_name_and_value_list" in gram.y
+static void deparseJsonKeyValueList(DeparseState *state, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseJsonKeyValue(state, lfirst(lc));
+ removeTrailingSpace(state);
+ if (lnext(exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+}
+
+static void deparseJsonOutput(DeparseState *state, JsonOutput *json_output)
+{
+ if (json_output == NULL)
+ return;
+
+ Assert(json_output->returning != NULL);
+
+ deparseAppendStringInfoString(state, "RETURNING ");
+ deparseTypeName(state, json_output->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonFormat(state, json_output->returning->format);
+}
+
+// "json_aggregate_func" and "func_expr" in gram.y
+static void deparseJsonObjectAgg(DeparseState *state, JsonObjectAgg *json_object_agg)
+{
+ Assert(json_object_agg->constructor != NULL);
+
+ deparseAppendStringInfoString(state, "JSON_OBJECTAGG(");
+ deparseJsonKeyValue(state, json_object_agg->arg);
+
+ if (json_object_agg->absent_on_null)
+ deparseAppendStringInfoString(state, "ABSENT ON NULL ");
+
+ if (json_object_agg->unique)
+ deparseAppendStringInfoString(state, "WITH UNIQUE ");
+
+ deparseJsonOutput(state, json_object_agg->constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (json_object_agg->constructor->agg_filter)
+ {
+ deparseAppendStringInfoString(state, "FILTER (WHERE ");
+ deparseExpr(state, json_object_agg->constructor->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (json_object_agg->constructor->over)
+ {
+ struct WindowDef *over = json_object_agg->constructor->over;
+ deparseAppendStringInfoString(state, "OVER ");
+ if (over->name)
+ deparseAppendStringInfoString(state, over->name);
+ else
+ deparseWindowDef(state, over);
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "json_aggregate_func" and "func_expr" in gram.y
+static void deparseJsonArrayAgg(DeparseState *state, JsonArrayAgg *json_array_agg)
+{
+ Assert(json_array_agg->constructor != NULL);
+
+ deparseAppendStringInfoString(state, "JSON_ARRAYAGG(");
+ deparseJsonValueExpr(state, json_array_agg->arg);
+ deparseOptSortClause(state, json_array_agg->constructor->agg_order, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (!json_array_agg->absent_on_null)
+ deparseAppendStringInfoString(state, "NULL ON NULL ");
+
+ deparseJsonOutput(state, json_array_agg->constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (json_array_agg->constructor->agg_filter)
+ {
+ deparseAppendStringInfoString(state, "FILTER (WHERE ");
+ deparseExpr(state, json_array_agg->constructor->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (json_array_agg->constructor->over)
+ {
+ struct WindowDef *over = json_array_agg->constructor->over;
+ deparseAppendStringInfoString(state, "OVER ");
+ if (over->name)
+ deparseAppendStringInfoString(state, over->name);
+ else
+ deparseWindowDef(state, over);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseJsonObjectConstructor(DeparseState *state, JsonObjectConstructor *json_object_constructor)
+{
+ deparseAppendStringInfoString(state, "JSON_OBJECT(");
+ deparseJsonKeyValueList(state, json_object_constructor->exprs);
+
+ if (json_object_constructor->absent_on_null)
+ deparseAppendStringInfoString(state, "ABSENT ON NULL ");
+
+ if (json_object_constructor->unique)
+ deparseAppendStringInfoString(state, "WITH UNIQUE ");
+
+ deparseJsonOutput(state, json_object_constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonArrayConstructor(DeparseState *state, JsonArrayConstructor *json_array_constructor)
+{
+ deparseAppendStringInfoString(state, "JSON_ARRAY(");
+ deparseJsonValueExprList(state, json_array_constructor->exprs);
+
+ if (!json_array_constructor->absent_on_null)
+ deparseAppendStringInfoString(state, "NULL ON NULL ");
+
+ deparseJsonOutput(state, json_array_constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonArrayQueryConstructor(DeparseState *state, JsonArrayQueryConstructor *json_array_query_constructor)
+{
+ deparseAppendStringInfoString(state, "JSON_ARRAY(");
+
+ deparseSelectStmt(state, castNode(SelectStmt, json_array_query_constructor->query), DEPARSE_NODE_CONTEXT_NONE);
+ deparseJsonFormat(state, json_array_query_constructor->format);
+ deparseJsonOutput(state, json_array_query_constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonParseExpr(DeparseState *state, JsonParseExpr *json_parse_expr)
+{
+ deparseAppendStringInfoString(state, "JSON(");
+
+ deparseJsonValueExpr(state, json_parse_expr->expr);
+
+ if (json_parse_expr->unique_keys)
+ deparseAppendStringInfoString(state, " WITH UNIQUE KEYS");
+
+ deparseAppendStringInfoString(state, ")");
+}
+
+static void deparseJsonScalarExpr(DeparseState *state, JsonScalarExpr *json_scalar_expr)
+{
+ deparseAppendStringInfoString(state, "JSON_SCALAR(");
+ deparseExpr(state, (Node*) json_scalar_expr->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ")");
+}
+
+static void deparseJsonSerializeExpr(DeparseState *state, JsonSerializeExpr *json_serialize_expr)
+{
+ deparseAppendStringInfoString(state, "JSON_SERIALIZE(");
+
+ deparseJsonValueExpr(state, json_serialize_expr->expr);
+
+ if (json_serialize_expr->output)
+ deparseJsonOutput(state, json_serialize_expr->output);
+
+ deparseAppendStringInfoString(state, ")");
+}
+
+static void deparseJsonQuotesClauseOpt(DeparseState *state, JsonQuotes quotes)
+{
+ switch (quotes)
+ {
+ case JS_QUOTES_UNSPEC:
+ break;
+ case JS_QUOTES_KEEP:
+ deparseAppendStringInfoString(state, " KEEP QUOTES");
+ break;
+ case JS_QUOTES_OMIT:
+ deparseAppendStringInfoString(state, " OMIT QUOTES");
+ break;
+ }
+}
+
+static void deparseJsonOnErrorClauseOpt(DeparseState *state, JsonBehavior *behavior)
+{
+ if (!behavior)
+ return;
+
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonBehavior(state, behavior);
+ deparseAppendStringInfoString(state, " ON ERROR");
+}
+
+static void deparseJsonOnEmptyClauseOpt(DeparseState *state, JsonBehavior *behavior)
+{
+ if (behavior)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonBehavior(state, behavior);
+ deparseAppendStringInfoString(state, " ON EMPTY");
+ }
+}
+
+static void deparseJsonFuncExpr(DeparseState *state, JsonFuncExpr *json_func_expr)
+{
+ switch (json_func_expr->op)
+ {
+ case JSON_EXISTS_OP:
+ deparseAppendStringInfoString(state, "JSON_EXISTS(");
+ break;
+ case JSON_QUERY_OP:
+ deparseAppendStringInfoString(state, "JSON_QUERY(");
+ break;
+ case JSON_VALUE_OP:
+ deparseAppendStringInfoString(state, "JSON_VALUE(");
+ break;
+ case JSON_TABLE_OP:
+ deparseAppendStringInfoString(state, "JSON_TABLE(");
+ break;
+ }
+
+ deparseJsonValueExpr(state, json_func_expr->context_item);
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, json_func_expr->pathspec, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (json_func_expr->passing)
+ deparseAppendStringInfoString(state, " PASSING ");
+
+ ListCell *lc = NULL;
+ foreach (lc, json_func_expr->passing)
+ {
+ JsonArgument *json_argument = castNode(JsonArgument, lfirst(lc));
+ deparseJsonValueExpr(state, json_argument->val);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseColLabel(state, json_argument->name);
+
+ if (lnext(json_func_expr->passing, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ if (json_func_expr->output)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonOutput(state, json_func_expr->output);
+ }
+
+ switch (json_func_expr->wrapper)
+ {
+ case JSW_UNSPEC:
+ break;
+ case JSW_NONE:
+ deparseAppendStringInfoString(state, " WITHOUT WRAPPER");
+ break;
+ case JSW_CONDITIONAL:
+ deparseAppendStringInfoString(state, " WITH CONDITIONAL WRAPPER");
+ break;
+ case JSW_UNCONDITIONAL:
+ deparseAppendStringInfoString(state, " WITH UNCONDITIONAL WRAPPER");
+ break;
+ }
+
+ deparseJsonQuotesClauseOpt(state, json_func_expr->quotes);
+ deparseJsonOnEmptyClauseOpt(state, json_func_expr->on_empty);
+ deparseJsonOnErrorClauseOpt(state, json_func_expr->on_error);
+
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonTablePathSpec(DeparseState *state, JsonTablePathSpec *json_table_path_spec)
+{
+ deparseStringLiteral(state, castNode(A_Const, json_table_path_spec->string)->val.sval.sval);
+
+ if (json_table_path_spec->name)
+ {
+ deparseAppendStringInfoString(state, " AS ");
+ deparseColLabel(state, json_table_path_spec->name);
+ }
+}
+
+// "json_behavior" in gram.y
+static void deparseJsonBehavior(DeparseState *state, JsonBehavior *json_behavior)
+{
+ switch (json_behavior->btype)
+ {
+ case JSON_BEHAVIOR_NULL:
+ deparseAppendStringInfoString(state, "NULL");
+ break;
+ case JSON_BEHAVIOR_ERROR:
+ deparseAppendStringInfoString(state, "ERROR");
+ break;
+ case JSON_BEHAVIOR_EMPTY:
+ deparseAppendStringInfoString(state, "EMPTY");
+ break;
+ case JSON_BEHAVIOR_TRUE:
+ deparseAppendStringInfoString(state, "TRUE");
+ break;
+ case JSON_BEHAVIOR_FALSE:
+ deparseAppendStringInfoString(state, "FALSE");
+ break;
+ case JSON_BEHAVIOR_EMPTY_ARRAY:
+ deparseAppendStringInfoString(state, "EMPTY ARRAY");
+ break;
+ case JSON_BEHAVIOR_EMPTY_OBJECT:
+ deparseAppendStringInfoString(state, "EMPTY OBJECT");
+ break;
+ case JSON_BEHAVIOR_DEFAULT:
+ deparseAppendStringInfoString(state, "DEFAULT ");
+ deparseExpr(state, (Node*) json_behavior->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ break;
+ case JSON_BEHAVIOR_UNKNOWN:
+ deparseAppendStringInfoString(state, "UNKNOWN");
+ break;
+ }
+}
+
+static void deparseJsonTableColumn(DeparseState *state, JsonTableColumn *json_table_column)
+{
+ if (json_table_column->coltype == JTC_NESTED)
+ {
+ deparseAppendStringInfoString(state, "NESTED PATH ");
+ deparseJsonTablePathSpec(state, json_table_column->pathspec);
+ deparseJsonTableColumns(state, json_table_column->columns);
+ return;
+ }
+
+ deparseColLabel(state, json_table_column->name);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (json_table_column->coltype)
+ {
+ case JTC_FOR_ORDINALITY:
+ deparseAppendStringInfoString(state, " FOR ORDINALITY");
+ break;
+ case JTC_EXISTS:
+ case JTC_FORMATTED:
+ case JTC_REGULAR:
+ deparseTypeName(state, json_table_column->typeName);
+
+ if (json_table_column->coltype == JTC_EXISTS)
+ deparseAppendStringInfoString(state, " EXISTS ");
+ else
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (json_table_column->format)
+ deparseJsonFormat(state, json_table_column->format);
+
+ if (json_table_column->pathspec)
+ {
+ deparseAppendStringInfoString(state, "PATH ");
+ deparseJsonTablePathSpec(state, json_table_column->pathspec);
+ }
+ break;
+ case JTC_NESTED:
+ Assert(false);
+ }
+
+ switch (json_table_column->wrapper)
+ {
+ case JSW_UNSPEC:
+ break;
+ case JSW_NONE:
+ if (json_table_column->coltype == JTC_REGULAR || json_table_column->coltype == JTC_FORMATTED)
+ deparseAppendStringInfoString(state, " WITHOUT WRAPPER");
+ break;
+ case JSW_CONDITIONAL:
+ deparseAppendStringInfoString(state, " WITH CONDITIONAL WRAPPER");
+ break;
+ case JSW_UNCONDITIONAL:
+ deparseAppendStringInfoString(state, " WITH UNCONDITIONAL WRAPPER");
+ break;
+ }
+
+ deparseJsonQuotesClauseOpt(state, json_table_column->quotes);
+ deparseJsonOnEmptyClauseOpt(state, json_table_column->on_empty);
+ deparseJsonOnErrorClauseOpt(state, json_table_column->on_error);
+}
+
+static void deparseJsonTableColumns(DeparseState *state, List *json_table_columns)
+{
+ deparseAppendStringInfoString(state, " COLUMNS (");
+
+ ListCell *lc = NULL;
+ foreach(lc, json_table_columns)
+ {
+ deparseJsonTableColumn(state, castNode(JsonTableColumn, lfirst(lc)));
+
+ if (lnext(json_table_columns, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonTable(DeparseState *state, JsonTable *json_table)
+{
+ deparseAppendStringInfoString(state, "JSON_TABLE(");
+
+ deparseJsonValueExpr(state, json_table->context_item);
+ deparseAppendStringInfoString(state, ", ");
+ deparseJsonTablePathSpec(state, json_table->pathspec);
+
+ if (json_table->passing)
+ deparseAppendStringInfoString(state, " PASSING ");
+
+ ListCell *lc = NULL;
+ foreach (lc, json_table->passing)
+ {
+ JsonArgument *json_argument = castNode(JsonArgument, lfirst(lc));
+ deparseJsonValueExpr(state, json_argument->val);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseColLabel(state, json_argument->name);
+
+ if (lnext(json_table->passing, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseJsonTableColumns(state, json_table->columns);
+
+ if (json_table->on_error)
+ {
+ deparseJsonBehavior(state, json_table->on_error);
+ deparseAppendStringInfoString(state, " ON ERROR");
+ }
+
+ deparseAppendStringInfoChar(state, ')');
+
+ if (json_table->alias)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseAlias(state, json_table->alias);
+ }
+}
+
+static void deparseGroupingFunc(DeparseState *state, GroupingFunc *grouping_func)
+{
+ deparseAppendStringInfoString(state, "GROUPING(");
+ deparseExprList(state, grouping_func->args);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseClusterStmt(DeparseState *state, ClusterStmt *cluster_stmt)
+{
+ deparseAppendStringInfoString(state, "CLUSTER ");
+
+ deparseUtilityOptionList(state, cluster_stmt->params);
+
+ if (cluster_stmt->relation != NULL)
+ {
+ deparseRangeVar(state, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (cluster_stmt->indexname != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(cluster_stmt->indexname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseValue(DeparseState *state, union ValUnion *value, DeparseNodeContext context)
+{
+ if (!value) {
+ deparseAppendStringInfoString(state, "NULL");
+ return;
+ }
+
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ case T_Float:
+ deparseNumericOnly(state, value);
+ break;
+ case T_Boolean:
+ deparseAppendStringInfoString(state, value->boolval.boolval ? "true" : "false");
+ break;
+ case T_String:
+ if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
+ deparseAppendStringInfoString(state, quote_identifier(value->sval.sval));
+ } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
+ deparseStringLiteral(state, value->sval.sval);
+ } else {
+ deparseAppendStringInfoString(state, value->sval.sval);
+ }
+ break;
+ case T_BitString:
+ if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'x')
+ {
+ deparseAppendStringInfoChar(state, 'x');
+ deparseStringLiteral(state, value->sval.sval + 1);
+ }
+ else if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'b')
+ {
+ deparseAppendStringInfoChar(state, 'b');
+ deparseStringLiteral(state, value->sval.sval + 1);
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ default:
+ elog(ERROR, "deparse: unrecognized value node type: %d",
+ (int) nodeTag(value));
+ break;
+ }
+}
+
+// "PrepareableStmt" in gram.y
+static void deparsePreparableStmt(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(state, castNode(SelectStmt, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(state, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(state, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(state, castNode(DeleteStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(state, castNode(MergeStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "RuleActionStmt" in gram.y
+static void deparseRuleActionStmt(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(state, castNode(SelectStmt, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(state, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(state, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(state, castNode(DeleteStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(state, castNode(NotifyStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "ExplainableStmt" in gram.y
+static void deparseExplainableStmt(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(state, castNode(SelectStmt, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(state, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(state, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(state, castNode(DeleteStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(state, castNode(DeclareCursorStmt, node));
+ break;
+ case T_CreateTableAsStmt:
+ deparseCreateTableAsStmt(state, castNode(CreateTableAsStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(state, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(state, castNode(ExecuteStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(state, castNode(MergeStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "schema_stmt" in gram.y
+static void deparseSchemaStmt(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_CreateStmt:
+ deparseCreateStmt(state, castNode(CreateStmt, node), false);
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(state, castNode(IndexStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(state, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(state, castNode(CreateTrigStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(state, castNode(GrantStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(state, castNode(ViewStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "stmt" in gram.y
+static void deparseStmt(DeparseState *state, Node *node)
+{
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ // For statements that can be nested, push/pop is handled directly in the
+ // respective deparse...Stmt methods
+ bool skip_push_pop = IsA(node, SelectStmt) ||
+ IsA(node, InsertStmt) ||
+ IsA(node, UpdateStmt) ||
+ IsA(node, DeleteStmt) ||
+ IsA(node, MergeStmt);
+
+ if (!skip_push_pop)
+ parent_level = deparseStateIncreaseNestingLevel(state);
+
+ // Note the following grammar names are missing in the list, because they
+ // get mapped to other node types:
+ //
+ // - AlterForeignTableStmt (=> AlterTableStmt)
+ // - AlterGroupStmt (=> AlterRoleStmt)
+ // - AlterCompositeTypeStmt (=> AlterTableStmt)
+ // - AnalyzeStmt (=> VacuumStmt)
+ // - CreateGroupStmt (=> CreateRoleStmt)
+ // - CreateMatViewStmt (=> CreateTableAsStmt)
+ // - CreateUserStmt (=> CreateRoleStmt)
+ // - DropCastStmt (=> DropStmt)
+ // - DropOpClassStmt (=> DropStmt)
+ // - DropOpFamilyStmt (=> DropStmt)
+ // - DropPLangStmt (=> DropPLangStmt)
+ // - DropTransformStmt (=> DropStmt)
+ // - RemoveAggrStmt (=> DropStmt)
+ // - RemoveFuncStmt (=> DropStmt)
+ // - RemoveOperStmt (=> DropStmt)
+ // - RevokeStmt (=> GrantStmt)
+ // - RevokeRoleStmt (=> GrantRoleStmt)
+ // - VariableResetStmt (=> VariableSetStmt)
+ //
+ // And the following grammar names error out in the parser:
+ // - CreateAssertionStmt (not supported yet)
+ switch (nodeTag(node))
+ {
+ case T_AlterEventTrigStmt:
+ deparseAlterEventTrigStmt(state, castNode(AlterEventTrigStmt, node));
+ break;
+ case T_AlterCollationStmt:
+ deparseAlterCollationStmt(state, castNode(AlterCollationStmt, node));
+ break;
+ case T_AlterDatabaseStmt:
+ deparseAlterDatabaseStmt(state, castNode(AlterDatabaseStmt, node));
+ break;
+ case T_AlterDatabaseSetStmt:
+ deparseAlterDatabaseSetStmt(state, castNode(AlterDatabaseSetStmt, node));
+ break;
+ case T_AlterDefaultPrivilegesStmt:
+ deparseAlterDefaultPrivilegesStmt(state, castNode(AlterDefaultPrivilegesStmt, node));
+ break;
+ case T_AlterDomainStmt:
+ deparseAlterDomainStmt(state, castNode(AlterDomainStmt, node));
+ break;
+ case T_AlterEnumStmt:
+ deparseAlterEnumStmt(state, castNode(AlterEnumStmt, node));
+ break;
+ case T_AlterExtensionStmt:
+ deparseAlterExtensionStmt(state, castNode(AlterExtensionStmt, node));
+ break;
+ case T_AlterExtensionContentsStmt:
+ deparseAlterExtensionContentsStmt(state, castNode(AlterExtensionContentsStmt, node));
+ break;
+ case T_AlterFdwStmt:
+ deparseAlterFdwStmt(state, castNode(AlterFdwStmt, node));
+ break;
+ case T_AlterForeignServerStmt:
+ deparseAlterForeignServerStmt(state, castNode(AlterForeignServerStmt, node));
+ break;
+ case T_AlterFunctionStmt:
+ deparseAlterFunctionStmt(state, castNode(AlterFunctionStmt, node));
+ break;
+ case T_AlterObjectDependsStmt:
+ deparseAlterObjectDependsStmt(state, castNode(AlterObjectDependsStmt, node));
+ break;
+ case T_AlterObjectSchemaStmt:
+ deparseAlterObjectSchemaStmt(state, castNode(AlterObjectSchemaStmt, node));
+ break;
+ case T_AlterOwnerStmt:
+ deparseAlterOwnerStmt(state, castNode(AlterOwnerStmt, node));
+ break;
+ case T_AlterOperatorStmt:
+ deparseAlterOperatorStmt(state, castNode(AlterOperatorStmt, node));
+ break;
+ case T_AlterTypeStmt:
+ deparseAlterTypeStmt(state, castNode(AlterTypeStmt, node));
+ break;
+ case T_AlterPolicyStmt:
+ deparseAlterPolicyStmt(state, castNode(AlterPolicyStmt, node));
+ break;
+ case T_AlterSeqStmt:
+ deparseAlterSeqStmt(state, castNode(AlterSeqStmt, node));
+ break;
+ case T_AlterSystemStmt:
+ deparseAlterSystemStmt(state, castNode(AlterSystemStmt, node));
+ break;
+ case T_AlterTableMoveAllStmt:
+ deparseAlterTableMoveAllStmt(state, castNode(AlterTableMoveAllStmt, node));
+ break;
+ case T_AlterTableStmt:
+ deparseAlterTableStmt(state, castNode(AlterTableStmt, node));
+ break;
+ case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
+ deparseAlterTableSpaceOptionsStmt(state, castNode(AlterTableSpaceOptionsStmt, node));
+ break;
+ case T_AlterPublicationStmt:
+ deparseAlterPublicationStmt(state, castNode(AlterPublicationStmt, node));
+ break;
+ case T_AlterRoleSetStmt:
+ deparseAlterRoleSetStmt(state, castNode(AlterRoleSetStmt, node));
+ break;
+ case T_AlterRoleStmt:
+ deparseAlterRoleStmt(state, castNode(AlterRoleStmt, node));
+ break;
+ case T_AlterSubscriptionStmt:
+ deparseAlterSubscriptionStmt(state, castNode(AlterSubscriptionStmt, node));
+ break;
+ case T_AlterStatsStmt:
+ deparseAlterStatsStmt(state, castNode(AlterStatsStmt, node));
+ break;
+ case T_AlterTSConfigurationStmt:
+ deparseAlterTSConfigurationStmt(state, castNode(AlterTSConfigurationStmt, node));
+ break;
+ case T_AlterTSDictionaryStmt:
+ deparseAlterTSDictionaryStmt(state, castNode(AlterTSDictionaryStmt, node));
+ break;
+ case T_AlterUserMappingStmt:
+ deparseAlterUserMappingStmt(state, castNode(AlterUserMappingStmt, node));
+ break;
+ case T_CallStmt:
+ deparseCallStmt(state, castNode(CallStmt, node));
+ break;
+ case T_CheckPointStmt:
+ deparseCheckPointStmt(state, castNode(CheckPointStmt, node));
+ break;
+ case T_ClosePortalStmt:
+ deparseClosePortalStmt(state, castNode(ClosePortalStmt, node));
+ break;
+ case T_ClusterStmt:
+ deparseClusterStmt(state, castNode(ClusterStmt, node));
+ break;
+ case T_CommentStmt:
+ deparseCommentStmt(state, castNode(CommentStmt, node));
+ break;
+ case T_ConstraintsSetStmt:
+ deparseConstraintsSetStmt(state, castNode(ConstraintsSetStmt, node));
+ break;
+ case T_CopyStmt:
+ deparseCopyStmt(state, castNode(CopyStmt, node));
+ break;
+ case T_CreateAmStmt:
+ deparseCreateAmStmt(state, castNode(CreateAmStmt, node));
+ break;
+ case T_CreateTableAsStmt: // "CreateAsStmt" in gram.y
+ deparseCreateTableAsStmt(state, castNode(CreateTableAsStmt, node));
+ break;
+ case T_CreateCastStmt:
+ deparseCreateCastStmt(state, castNode(CreateCastStmt, node));
+ break;
+ case T_CreateConversionStmt:
+ deparseCreateConversionStmt(state, castNode(CreateConversionStmt, node));
+ break;
+ case T_CreateDomainStmt:
+ deparseCreateDomainStmt(state, castNode(CreateDomainStmt, node));
+ break;
+ case T_CreateExtensionStmt:
+ deparseCreateExtensionStmt(state, castNode(CreateExtensionStmt, node));
+ break;
+ case T_CreateFdwStmt:
+ deparseCreateFdwStmt(state, castNode(CreateFdwStmt, node));
+ break;
+ case T_CreateForeignServerStmt:
+ deparseCreateForeignServerStmt(state, castNode(CreateForeignServerStmt, node));
+ break;
+ case T_CreateForeignTableStmt:
+ deparseCreateForeignTableStmt(state, castNode(CreateForeignTableStmt, node));
+ break;
+ case T_CreateFunctionStmt:
+ deparseCreateFunctionStmt(state, castNode(CreateFunctionStmt, node));
+ break;
+ case T_CreateOpClassStmt:
+ deparseCreateOpClassStmt(state, castNode(CreateOpClassStmt, node));
+ break;
+ case T_CreateOpFamilyStmt:
+ deparseCreateOpFamilyStmt(state, castNode(CreateOpFamilyStmt, node));
+ break;
+ case T_CreatePublicationStmt:
+ deparseCreatePublicationStmt(state, castNode(CreatePublicationStmt, node));
+ break;
+ case T_AlterOpFamilyStmt:
+ deparseAlterOpFamilyStmt(state, castNode(AlterOpFamilyStmt, node));
+ break;
+ case T_CreatePolicyStmt:
+ deparseCreatePolicyStmt(state, castNode(CreatePolicyStmt, node));
+ break;
+ case T_CreatePLangStmt:
+ deparseCreatePLangStmt(state, castNode(CreatePLangStmt, node));
+ break;
+ case T_CreateSchemaStmt:
+ deparseCreateSchemaStmt(state, castNode(CreateSchemaStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(state, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateStmt:
+ deparseCreateStmt(state, castNode(CreateStmt, node), false);
+ break;
+ case T_CreateSubscriptionStmt:
+ deparseCreateSubscriptionStmt(state, castNode(CreateSubscriptionStmt, node));
+ break;
+ case T_CreateStatsStmt:
+ deparseCreateStatsStmt(state, castNode(CreateStatsStmt, node));
+ break;
+ case T_CreateTableSpaceStmt:
+ deparseCreateTableSpaceStmt(state, castNode(CreateTableSpaceStmt, node));
+ break;
+ case T_CreateTransformStmt:
+ deparseCreateTransformStmt(state, castNode(CreateTransformStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(state, castNode(CreateTrigStmt, node));
+ break;
+ case T_CreateEventTrigStmt:
+ deparseCreateEventTrigStmt(state, castNode(CreateEventTrigStmt, node));
+ break;
+ case T_CreateRoleStmt:
+ deparseCreateRoleStmt(state, castNode(CreateRoleStmt, node));
+ break;
+ case T_CreateUserMappingStmt:
+ deparseCreateUserMappingStmt(state, castNode(CreateUserMappingStmt, node));
+ break;
+ case T_CreatedbStmt:
+ deparseCreatedbStmt(state, castNode(CreatedbStmt, node));
+ break;
+ case T_DeallocateStmt:
+ deparseDeallocateStmt(state, castNode(DeallocateStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(state, castNode(DeclareCursorStmt, node));
+ break;
+ case T_DefineStmt:
+ deparseDefineStmt(state, castNode(DefineStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(state, castNode(DeleteStmt, node));
+ break;
+ case T_DiscardStmt:
+ deparseDiscardStmt(state, castNode(DiscardStmt, node));
+ break;
+ case T_DoStmt:
+ deparseDoStmt(state, castNode(DoStmt, node));
+ break;
+ case T_DropOwnedStmt:
+ deparseDropOwnedStmt(state, castNode(DropOwnedStmt, node));
+ break;
+ case T_DropStmt:
+ deparseDropStmt(state, castNode(DropStmt, node));
+ break;
+ case T_DropSubscriptionStmt:
+ deparseDropSubscriptionStmt(state, castNode(DropSubscriptionStmt, node));
+ break;
+ case T_DropTableSpaceStmt:
+ deparseDropTableSpaceStmt(state, castNode(DropTableSpaceStmt, node));
+ break;
+ case T_DropRoleStmt:
+ deparseDropRoleStmt(state, castNode(DropRoleStmt, node));
+ break;
+ case T_DropUserMappingStmt:
+ deparseDropUserMappingStmt(state, castNode(DropUserMappingStmt, node));
+ break;
+ case T_DropdbStmt:
+ deparseDropdbStmt(state, castNode(DropdbStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(state, castNode(ExecuteStmt, node));
+ break;
+ case T_ExplainStmt:
+ deparseExplainStmt(state, castNode(ExplainStmt, node));
+ break;
+ case T_FetchStmt:
+ deparseFetchStmt(state, castNode(FetchStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(state, castNode(GrantStmt, node));
+ break;
+ case T_GrantRoleStmt:
+ deparseGrantRoleStmt(state, castNode(GrantRoleStmt, node));
+ break;
+ case T_ImportForeignSchemaStmt:
+ deparseImportForeignSchemaStmt(state, castNode(ImportForeignSchemaStmt, node));
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(state, castNode(IndexStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(state, castNode(InsertStmt, node));
+ break;
+ case T_ListenStmt:
+ deparseListenStmt(state, castNode(ListenStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(state, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_LoadStmt:
+ deparseLoadStmt(state, castNode(LoadStmt, node));
+ break;
+ case T_LockStmt:
+ deparseLockStmt(state, castNode(LockStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(state, castNode(MergeStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(state, castNode(NotifyStmt, node));
+ break;
+ case T_PrepareStmt:
+ deparsePrepareStmt(state, castNode(PrepareStmt, node));
+ break;
+ case T_ReassignOwnedStmt:
+ deparseReassignOwnedStmt(state, castNode(ReassignOwnedStmt, node));
+ break;
+ case T_ReindexStmt:
+ deparseReindexStmt(state, castNode(ReindexStmt, node));
+ break;
+ case T_RenameStmt:
+ deparseRenameStmt(state, castNode(RenameStmt, node));
+ break;
+ case T_RuleStmt:
+ deparseRuleStmt(state, castNode(RuleStmt, node));
+ break;
+ case T_SecLabelStmt:
+ deparseSecLabelStmt(state, castNode(SecLabelStmt, node));
+ break;
+ case T_SelectStmt:
+ deparseSelectStmt(state, castNode(SelectStmt, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_TransactionStmt:
+ deparseTransactionStmt(state, castNode(TransactionStmt, node));
+ break;
+ case T_TruncateStmt:
+ deparseTruncateStmt(state, castNode(TruncateStmt, node));
+ break;
+ case T_UnlistenStmt:
+ deparseUnlistenStmt(state, castNode(UnlistenStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(state, castNode(UpdateStmt, node));
+ break;
+ case T_VacuumStmt:
+ deparseVacuumStmt(state, castNode(VacuumStmt, node));
+ break;
+ case T_VariableSetStmt:
+ deparseVariableSetStmt(state, castNode(VariableSetStmt, node));
+ break;
+ case T_VariableShowStmt:
+ deparseVariableShowStmt(state, castNode(VariableShowStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(state, castNode(ViewStmt, node));
+ break;
+ // These node types are created by DefineStmt grammar for CREATE TYPE in some cases
+ case T_CompositeTypeStmt:
+ deparseCompositeTypeStmt(state, castNode(CompositeTypeStmt, node));
+ break;
+ case T_CreateEnumStmt:
+ deparseCreateEnumStmt(state, castNode(CreateEnumStmt, node));
+ break;
+ case T_CreateRangeStmt:
+ deparseCreateRangeStmt(state, castNode(CreateRangeStmt, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
+ }
+
+ if (!skip_push_pop)
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+#endif
diff --git a/postgres_deparse.18.c b/postgres_deparse.18.c
new file mode 100644
index 0000000..4f56f9a
--- /dev/null
+++ b/postgres_deparse.18.c
@@ -0,0 +1,12257 @@
+#include "pg_config.h"
+#if(PG_MAJORVERSION_NUM == 18)
+
+// From https://github.com/pganalyze/libpg_query/blob/18.0.0/src/postgres_deparse.c
+
+// Copyright (c) 2015, Lukas Fittl
+// Copyright (c) 2016-2023, Duboce Labs, Inc. (pganalyze)
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "postgres_deparse.h"
+
+#include "postgres.h"
+#include "catalog/index.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_trigger.h"
+#include "commands/trigger.h"
+#include "common/keywords.h"
+#include "common/kwlookup.h"
+#include "lib/stringinfo.h"
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "utils/builtins.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/xml.h"
+
+/*
+ * # Deparser overview
+ *
+ * The deparser works by walking the input parse tree and emitting into the
+ * currently active "part" as pointed to (indirectly) by the state struct.
+ *
+ * A lot of the structure of the deparser described below is meant to support
+ * the optional "pretty print" mode that can be enabled and configured through
+ * the deparser options, and inserts whitespace (newlines/spaces) as needed to
+ * make the output easier to read.
+ *
+ * ## Nesting levels
+ *
+ * Starting at the state struct we have a currently active "nesting level",
+ * which indicates the base indentation, as well as contains one or more part
+ * groups, each of which has one or more parts.
+ *
+ * Nesting levels are typically opened, or "increased", when processing a new
+ * statement contained within other statements, or for certain statement-like
+ * constructs (e.g. CASE clauses) that require custom indendation.
+ *
+ * Nesting levels are closed, or "decreased", when exiting such statements or
+ * statement-like constructs. During this operation all parts and subparts get
+ * flattened (turned into a simple list of parts), and are added to the parent
+ * nesting level.
+ *
+ * At the end of the tree walk the parts of the top most nesting level get
+ * emitted into the output string, formatted based on the deparse options.
+ *
+ * ## Part groups
+ *
+ * Part groups are usually started for each "major" keyword, which is chosen
+ * for how the output is intended to be laid out. For example, the "FROM"
+ * keyword in a SELECT statement is considered "major" and starts a new part
+ * group, vs the "JOIN" keyword is not, and as such both regular tables and
+ * JOIN clauses will be within one part group.
+ *
+ * ## Parts, indentation and merging
+ *
+ * The parts contained in part groups may be indented one additional level
+ * beyond the base indentation of the currently active nesting level, to help
+ * differentiate them from the major keywords. This can be turned off with
+ * DEPARSE_PART_NO_INDENT, for example as needed to format WITH clauses
+ * effectively.
+ *
+ * Parts may be merged with other parts within the same group, if the indent
+ * mode is set to DEPARSE_PART_INDENT_AND_MERGE. This is utilized to put
+ * certain items, for example the target list items in SELECT on one or more
+ * lines, breaking at separators as needed to respect the maximum line limit.
+ *
+ * ## Node context
+ *
+ * Node context is used when the same function in the deparser needs to behave
+ * differently depending on the parent node. For example, a SELECT statement
+ * needs wrapping parenthesis in certain situations where the parent statement
+ * uses a set operation (e.g. UNION).
+ *
+ * ## Comments
+ *
+ * Comments do not exist as nodes in a Postgres parse tree, and as such need to
+ * be passed in separately through the deparser options. They are placed in the
+ * output on a best effort basis, by matching against node locations. Comments
+ * will only be output at most once, but may not be output at all in certain
+ * cases, for example when the comment's specified match location is never
+ * reached by any of the nodes visited.
+ */
+
+typedef enum DeparseNodeContext {
+ DEPARSE_NODE_CONTEXT_NONE,
+ // Parent node type (and sometimes field)
+ DEPARSE_NODE_CONTEXT_INSERT_RELATION,
+ DEPARSE_NODE_CONTEXT_INSERT_SELECT,
+ DEPARSE_NODE_CONTEXT_A_EXPR,
+ DEPARSE_NODE_CONTEXT_CREATE_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_TYPE,
+ DEPARSE_NODE_CONTEXT_ALTER_DOMAIN,
+ DEPARSE_NODE_CONTEXT_SET_STATEMENT,
+ DEPARSE_NODE_CONTEXT_FUNC_EXPR,
+ DEPARSE_NODE_CONTEXT_SELECT_SETOP,
+ DEPARSE_NODE_CONTEXT_SELECT_SORT_CLAUSE,
+ // Identifier vs constant context
+ DEPARSE_NODE_CONTEXT_IDENTIFIER,
+ DEPARSE_NODE_CONTEXT_CONSTANT
+} DeparseNodeContext;
+
+typedef enum DeparsePartIndentMode {
+ /* Don't indent parts at all, used in special cases (e.g. WITH clauses) */
+ DEPARSE_PART_NO_INDENT,
+
+ /* Indent parts but don't merge them (keep each on their own line) */
+ DEPARSE_PART_INDENT,
+
+ /* Indent parts and merge them together up to the max line length */
+ DEPARSE_PART_INDENT_AND_MERGE
+} DeparsePartIndentMode;
+
+// Each part is typically one line to be emitted in pretty print mode
+typedef struct DeparseStatePart
+{
+ StringInfo str;
+
+ /* If this gets emitted as its own line, number of spaces to be added as indentation */
+ int indent;
+
+ /* Allow merging this part with adjacent parts that are marked as mergeable */
+ bool mergeable;
+} DeparseStatePart;
+
+// A part group are typically all parts associated with a major keyword
+typedef struct DeparseStatePartGroup
+{
+ const char *keyword;
+ List *parts;
+ DeparsePartIndentMode indent_mode;
+} DeparseStatePartGroup;
+
+// Nesting levels may be statements, or complex parts of statements that should be indented (e.g. CASE)
+typedef struct DeparseStateNestingLevel
+{
+ /* List of DeparseStatePartGroup items */
+ List *part_groups;
+
+ /* Add this much indentation to every part */
+ int base_indent;
+} DeparseStateNestingLevel;
+
+typedef struct DeparseState
+{
+ DeparseStateNestingLevel *current;
+
+ /* List of DeparseStatePart items */
+ List *result_parts;
+
+ /* Deparse options originally passed in */
+ PostgresDeparseOpts *opts;
+
+ /* Set of indexes of comments already placed in the output query */
+ Bitmapset *emitted_comments;
+} DeparseState;
+
+static void deparseSelectStmt(DeparseState *state, SelectStmt *stmt, DeparseNodeContext context);
+static void deparseIntoClause(DeparseState *state, IntoClause *into_clause);
+static void deparseRangeVar(DeparseState *state, RangeVar *range_var, DeparseNodeContext context);
+static void deparseResTarget(DeparseState *state, ResTarget *res_target, DeparseNodeContext context);
+static void deparseAlias(DeparseState *state, Alias *alias);
+static void deparseWindowDef(DeparseState *state, WindowDef* window_def);
+static void deparseColumnRef(DeparseState *state, ColumnRef* column_ref);
+static void deparseSubLink(DeparseState *state, SubLink* sub_link);
+static void deparseAExpr(DeparseState *state, A_Expr* a_expr, DeparseNodeContext context);
+static void deparseBoolExpr(DeparseState *state, BoolExpr *bool_expr);
+static void deparseAStar(DeparseState *state, A_Star* a_star);
+static void deparseCollateClause(DeparseState *state, CollateClause* collate_clause);
+static void deparseSortBy(DeparseState *state, SortBy* sort_by);
+static void deparseParamRef(DeparseState *state, ParamRef* param_ref);
+static void deparseSQLValueFunction(DeparseState *state, SQLValueFunction* sql_value_function);
+static void deparseWithClause(DeparseState *state, WithClause *with_clause);
+static void deparseJoinExpr(DeparseState *state, JoinExpr *join_expr);
+static void deparseCommonTableExpr(DeparseState *state, CommonTableExpr *cte);
+static void deparseRangeSubselect(DeparseState *state, RangeSubselect *range_subselect);
+static void deparseRangeFunction(DeparseState *state, RangeFunction *range_func);
+static void deparseAArrayExpr(DeparseState *state, A_ArrayExpr * array_expr);
+static void deparseRowExpr(DeparseState *state, RowExpr *row_expr);
+static void deparseTypeCast(DeparseState *state, TypeCast *type_cast, DeparseNodeContext context);
+static void deparseTypeName(DeparseState *state, TypeName *type_name);
+static void deparseIntervalTypmods(DeparseState *state, TypeName *type_name);
+static void deparseNullTest(DeparseState *state, NullTest *null_test);
+static void deparseCaseExpr(DeparseState *state, CaseExpr *case_expr);
+static void deparseCaseWhen(DeparseState *state, CaseWhen *case_when);
+static void deparseAIndirection(DeparseState *state, A_Indirection *a_indirection);
+static void deparseAIndices(DeparseState *state, A_Indices *a_indices);
+static void deparseCoalesceExpr(DeparseState *state, CoalesceExpr *coalesce_expr);
+static void deparseBooleanTest(DeparseState *state, BooleanTest *boolean_test);
+static void deparseColumnDef(DeparseState *state, ColumnDef *column_def);
+static void deparseInsertStmt(DeparseState *state, InsertStmt *insert_stmt);
+static void deparseOnConflictClause(DeparseState *state, OnConflictClause *on_conflict_clause);
+static void deparseIndexElem(DeparseState *state, IndexElem* index_elem);
+static void deparseUpdateStmt(DeparseState *state, UpdateStmt *update_stmt);
+static void deparseDeleteStmt(DeparseState *state, DeleteStmt *delete_stmt);
+static void deparseLockingClause(DeparseState *state, LockingClause *locking_clause);
+static void deparseSetToDefault(DeparseState *state, SetToDefault *set_to_default);
+static void deparseCreateCastStmt(DeparseState *state, CreateCastStmt *create_cast_stmt);
+static void deparseCreateDomainStmt(DeparseState *state, CreateDomainStmt *create_domain_stmt);
+static void deparseFunctionParameter(DeparseState *state, FunctionParameter *function_parameter);
+static void deparseRoleSpec(DeparseState *state, RoleSpec *role_spec);
+static void deparseViewStmt(DeparseState *state, ViewStmt *view_stmt);
+static void deparseVariableSetStmt(DeparseState *state, VariableSetStmt* variable_set_stmt);
+static void deparseReplicaIdentityStmt(DeparseState *state, ReplicaIdentityStmt *replica_identity_stmt);
+static void deparseRangeTableSample(DeparseState *state, RangeTableSample *range_table_sample);
+static void deparseRangeTableFunc(DeparseState *state, RangeTableFunc* range_table_func);
+static void deparseGroupingSet(DeparseState *state, GroupingSet *grouping_set);
+static void deparseFuncCall(DeparseState *state, FuncCall *func_call, DeparseNodeContext context);
+static void deparseMinMaxExpr(DeparseState *state, MinMaxExpr *min_max_expr);
+static void deparseXmlExpr(DeparseState *state, XmlExpr* xml_expr, DeparseNodeContext context);
+static void deparseXmlSerialize(DeparseState *state, XmlSerialize *xml_serialize);
+static void deparseJsonIsPredicate(DeparseState *state, JsonIsPredicate *json_is_predicate);
+static void deparseJsonObjectAgg(DeparseState *state, JsonObjectAgg *json_object_agg);
+static void deparseJsonArrayAgg(DeparseState *state, JsonArrayAgg *json_array_agg);
+static void deparseJsonObjectConstructor(DeparseState *state, JsonObjectConstructor *json_object_constructor);
+static void deparseJsonArrayConstructor(DeparseState *state, JsonArrayConstructor *json_array_constructor);
+static void deparseJsonArrayQueryConstructor(DeparseState *state, JsonArrayQueryConstructor *json_array_query_constructor);
+static void deparseJsonValueExpr(DeparseState *state, JsonValueExpr *json_value_expr);
+static void deparseJsonOutput(DeparseState *state, JsonOutput *json_output);
+static void deparseJsonParseExpr(DeparseState *state, JsonParseExpr *json_parse_expr);
+static void deparseJsonScalarExpr(DeparseState *state, JsonScalarExpr *json_scalar_expr);
+static void deparseJsonSerializeExpr(DeparseState *state, JsonSerializeExpr *json_serialize_expr);
+static void deparseJsonTable(DeparseState *state, JsonTable *json_table);
+static void deparseJsonTableColumn(DeparseState *state, JsonTableColumn *json_table_column);
+static void deparseJsonTableColumns(DeparseState *state, List *json_table_columns);
+static void deparseJsonTablePathSpec(DeparseState *state, JsonTablePathSpec *json_table_path_spec);
+static void deparseJsonBehavior(DeparseState *state, JsonBehavior *json_behavior);
+static void deparseJsonFuncExpr(DeparseState *state, JsonFuncExpr *json_func_expr);
+static void deparseJsonQuotesClauseOpt(DeparseState *state, JsonQuotes quotes);
+static void deparseJsonOnErrorClauseOpt(DeparseState *state, JsonBehavior *behavior);
+static void deparseJsonOnEmptyClauseOpt(DeparseState *state, JsonBehavior *behavior);
+static void deparseConstraint(DeparseState *state, Constraint *constraint, DeparseNodeContext context);
+static void deparseATAlterConstraint(DeparseState *state, ATAlterConstraint *constraint);
+static void deparseSchemaStmt(DeparseState *state, Node *node);
+static void deparseExecuteStmt(DeparseState *state, ExecuteStmt *execute_stmt);
+static void deparseTriggerTransition(DeparseState *state, TriggerTransition *trigger_transition);
+static void deparseCreateOpClassItem(DeparseState *state, CreateOpClassItem *create_op_class_item);
+static void deparseAConst(DeparseState *state, A_Const *a_const);
+static void deparseGroupingFunc(DeparseState *state, GroupingFunc *grouping_func);
+
+static void deparsePreparableStmt(DeparseState *state, Node *node);
+static void deparseRuleActionStmt(DeparseState *state, Node *node);
+static void deparseExplainableStmt(DeparseState *state, Node *node);
+static void deparseStmt(DeparseState *state, Node *node);
+static void deparseValue(DeparseState *state, union ValUnion *value, DeparseNodeContext context);
+
+static void
+removeTrailingSpaceFromStr(StringInfo str)
+{
+ if (str->len >= 1 && str->data[str->len - 1] == ' ') {
+ str->len -= 1;
+ str->data[str->len] = '\0';
+ }
+}
+
+// Check whether the value is a reserved keyword, to determine escaping for output
+//
+// Note that since the parser lowercases all keywords, this does *not* match when the
+// value is not all-lowercase and a reserved keyword.
+static bool
+isReservedKeyword(const char *val)
+{
+ int kwnum = ScanKeywordLookup(val, &ScanKeywords);
+ bool all_lower_case = true;
+ const char *cp;
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ (*cp >= 'a' && *cp <= 'z') ||
+ (*cp >= '0' && *cp <= '9') ||
+ (*cp == '_')))
+ {
+ all_lower_case = false;
+ break;
+ }
+ }
+
+ return all_lower_case && kwnum >= 0 && ScanKeywordCategories[kwnum] == RESERVED_KEYWORD;
+}
+
+// Returns whether the given value consists only of operator characters
+static bool
+isOp(const char *val)
+{
+ const char *cp;
+
+ Assert(strlen(val) > 0);
+
+ for (cp = val; *cp; cp++)
+ {
+ if (!(
+ *cp == '~' ||
+ *cp == '!' ||
+ *cp == '@' ||
+ *cp == '#' ||
+ *cp == '^' ||
+ *cp == '&' ||
+ *cp == '|' ||
+ *cp == '`' ||
+ *cp == '?' ||
+ *cp == '+' ||
+ *cp == '-' ||
+ *cp == '*' ||
+ *cp == '/' ||
+ *cp == '%' ||
+ *cp == '<' ||
+ *cp == '>' ||
+ *cp == '='))
+ return false;
+ }
+
+ return true;
+}
+
+static DeparseStatePart *
+makeDeparseStatePart(DeparseState *state, DeparseStateNestingLevel *level, DeparsePartIndentMode indent_mode)
+{
+ DeparseStatePart *part = palloc(sizeof(DeparseStatePart));
+ part->str = makeStringInfo();
+ part->indent = level->base_indent;
+ if (indent_mode != DEPARSE_PART_NO_INDENT)
+ part->indent += state->opts->indent_size;
+ part->mergeable = indent_mode == DEPARSE_PART_INDENT_AND_MERGE;
+ return part;
+}
+
+static void
+freeDeparseStatePart(DeparseStatePart *part)
+{
+ pfree(part->str->data);
+ pfree(part->str);
+ pfree(part);
+}
+
+// Returns current active part group, and initializes the first one (including an empty part) if needed
+static DeparseStatePartGroup *
+deparseGetCurrentPartGroup(DeparseState *state)
+{
+ DeparseStateNestingLevel *level = state->current;
+ if (level->part_groups)
+ return (DeparseStatePartGroup *) llast(level->part_groups);
+
+ DeparseStatePartGroup *part_group = palloc0(sizeof(DeparseStatePartGroup));
+ part_group->parts = lappend(part_group->parts, makeDeparseStatePart(state, level, part_group->indent_mode));
+ level->part_groups = lappend(level->part_groups, part_group);
+ return part_group;
+}
+
+static DeparseStatePart *
+deparseGetCurrentPart(DeparseState *state)
+{
+ DeparseStatePartGroup *part_group = deparseGetCurrentPartGroup(state);
+ return (DeparseStatePart *) llast(part_group->parts);
+}
+
+static void
+deparseMarkCurrentPartNonMergable(DeparseState *state)
+{
+ DeparseStatePart *part = deparseGetCurrentPart(state);
+ part->mergeable = false;
+}
+
+static StringInfo deparseGetCurrentStringInfo(DeparseState *state)
+{
+ DeparseStatePart *part = deparseGetCurrentPart(state);
+ Assert(part != NULL);
+ return part->str;
+}
+
+static void deparseAppendStringInfo(DeparseState *state, const char *fmt,...)
+{
+ StringInfo str = deparseGetCurrentStringInfo(state);
+ int save_errno = errno;
+
+ for (;;)
+ {
+ va_list args;
+ int needed;
+
+ /* Try to format the data. */
+ errno = save_errno;
+ va_start(args, fmt);
+ needed = appendStringInfoVA(str, fmt, args);
+ va_end(args);
+
+ if (needed == 0)
+ break; /* success */
+
+ /* Increase the buffer size and try again. */
+ enlargeStringInfo(str, needed);
+ }
+}
+
+static void deparseAppendStringInfoString(DeparseState *state, const char *s)
+{
+ StringInfo str = deparseGetCurrentStringInfo(state);
+ appendStringInfoString(str, s);
+}
+
+static void deparseAppendStringInfoChar(DeparseState *state, char ch)
+{
+ StringInfo str = deparseGetCurrentStringInfo(state);
+ appendStringInfoChar(str, ch);
+}
+
+static void
+removeTrailingSpace(DeparseState *state)
+{
+ StringInfo str = deparseGetCurrentStringInfo(state);
+ removeTrailingSpaceFromStr(str);
+}
+
+static void
+deparseRemoveTrailingEmptyPart(DeparseState *state)
+{
+ DeparseStatePartGroup *part_group = deparseGetCurrentPartGroup(state);
+ DeparseStatePart *last_part = deparseGetCurrentPart(state);
+
+ if (last_part->str->len == 0)
+ {
+ freeDeparseStatePart(last_part);
+ part_group->parts = list_delete_last(part_group->parts);
+ }
+}
+
+static void
+deparseAppendPart(DeparseState *state, bool deduplicate)
+{
+ DeparseStatePartGroup *part_group = deparseGetCurrentPartGroup(state);
+
+ // Remove previous part if its empty and we deduplicate. We don't keep
+ // the existing part since it may have the wrong indent level or mode.
+ if (deduplicate)
+ deparseRemoveTrailingEmptyPart(state);
+
+ part_group->parts = lappend(part_group->parts, makeDeparseStatePart(state, state->current, part_group->indent_mode));
+}
+
+static void
+deparseAppendCommaAndPart(DeparseState *state)
+{
+ if (state->opts->commas_start_of_line)
+ {
+ deparseAppendPart(state, true);
+ deparseAppendStringInfoString(state, ", ");
+ }
+ else
+ {
+ deparseAppendStringInfoChar(state, ',');
+ deparseAppendPart(state, true);
+ }
+}
+
+static void
+deparseAppendPartGroup(DeparseState *state, const char *keyword, DeparsePartIndentMode indent_mode)
+{
+ DeparseStateNestingLevel *level = state->current;
+ DeparseStatePartGroup *part_group = palloc0(sizeof(DeparseStatePartGroup));
+
+ if (list_length(level->part_groups) > 0)
+ removeTrailingSpace(state);
+
+ part_group->keyword = keyword;
+ part_group->parts = lappend(part_group->parts, makeDeparseStatePart(state, state->current, indent_mode));
+ part_group->indent_mode = indent_mode;
+
+ level->part_groups = lappend(level->part_groups, part_group);
+}
+
+static void
+deparseAppendCommentsIfNeeded(DeparseState *state, ParseLoc location)
+{
+ for (int i = 0; i < state->opts->comment_count; i++)
+ {
+ if (bms_is_member(i, state->emitted_comments))
+ continue;
+
+ PostgresDeparseComment *comment = state->opts->comments[i];
+ if (comment->match_location > location)
+ continue;
+
+ // Emit one less leading newline if we already emitted one for formatting reasons
+ int newlines_before_comment = comment->newlines_before_comment;
+ if (state->opts->pretty_print && newlines_before_comment > 0 &&
+ deparseGetCurrentPartGroup(state)->keyword != NULL &&
+ deparseGetCurrentStringInfo(state)->len == 0)
+ newlines_before_comment -= 1;
+
+ for (int j = 0; j < newlines_before_comment; j++)
+ {
+ if (state->opts->pretty_print)
+ deparseAppendPart(state, false);
+ else
+ deparseAppendStringInfoChar(state, '\n');
+ }
+
+ deparseAppendStringInfoString(state, comment->str);
+
+ /* never merge comments with other parts */
+ deparseMarkCurrentPartNonMergable(state);
+
+ for (int j = 0; j < comment->newlines_after_comment; j++)
+ {
+ if (state->opts->pretty_print)
+ deparseAppendPart(state, false);
+ else
+ deparseAppendStringInfoChar(state, '\n');
+ }
+
+ state->emitted_comments = bms_add_member(state->emitted_comments, i);
+ }
+}
+
+static void
+deparseEmit(DeparseState *state, StringInfo str)
+{
+ ListCell *lc;
+
+ /* If the last part is empty, drop it, so we don't confuse the newline output */
+ DeparseStatePart *last_part = (DeparseStatePart *) llast(state->result_parts);
+ if (last_part && last_part->str->len == 0)
+ {
+ freeDeparseStatePart(last_part);
+ state->result_parts = list_delete_last(state->result_parts);
+ }
+
+ foreach (lc, state->result_parts)
+ {
+ DeparseStatePart *part = (DeparseStatePart *) lfirst(lc);
+ bool last_part = list_cell_number(state->result_parts, lc) == list_length(state->result_parts) - 1;
+
+ if (!state->opts->pretty_print && part->str->len > 0 && (part->str->data[0] == ')' || part->str->data[0] == ';'))
+ removeTrailingSpaceFromStr(str);
+
+ if (state->opts->pretty_print)
+ {
+ for (int i = 0; i < part->indent; i++)
+ appendStringInfoChar(str, ' ');
+ }
+
+ appendStringInfoString(str, part->str->data);
+ removeTrailingSpaceFromStr(str);
+
+ if (!last_part)
+ {
+ if (state->opts->pretty_print)
+ appendStringInfoChar(str, '\n');
+ else if (str->data[str->len - 1] != '(')
+ appendStringInfoChar(str, ' ');
+ }
+
+ freeDeparseStatePart(part);
+ }
+ list_free(state->result_parts);
+ state->result_parts = NIL;
+
+ if (state->opts->pretty_print && state->opts->trailing_newline)
+ appendStringInfoChar(str, '\n');
+}
+
+static DeparseStateNestingLevel *
+deparseStateIncreaseNestingLevel(DeparseState *state)
+{
+ DeparseStateNestingLevel *parent = state->current;
+ DeparseStateNestingLevel *level = palloc0(sizeof(DeparseStateNestingLevel));
+ if (parent)
+ {
+ DeparseStatePartGroup *part_group = deparseGetCurrentPartGroup(state);
+ level->base_indent = parent->base_indent + state->opts->indent_size;
+ if (part_group->indent_mode != DEPARSE_PART_NO_INDENT) /* Indent again if parts next to us are also indented */
+ level->base_indent += state->opts->indent_size;
+
+ /* Parts with nested elements don't get merged, even if otherwise permitted */
+ deparseMarkCurrentPartNonMergable(state);
+ }
+ state->current = level;
+ return parent;
+}
+
+static void
+deparseStateDecreaseNestingLevel(DeparseState *state, DeparseStateNestingLevel *parent_level)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ DeparseStateNestingLevel *level = state->current;
+ Assert(level != NULL);
+
+ foreach (lc, level->part_groups)
+ {
+ DeparseStatePartGroup *part_group = (DeparseStatePartGroup *) lfirst(lc);
+
+ /* Merge parts */
+ if (part_group->indent_mode == DEPARSE_PART_INDENT_AND_MERGE && list_length(part_group->parts) > 1)
+ {
+ DeparseStatePart *target = (DeparseStatePart *) linitial(part_group->parts);
+ for_each_from (lc2, part_group->parts, 1)
+ {
+ DeparseStatePart *part = (DeparseStatePart *) lfirst(lc2);
+ removeTrailingSpaceFromStr(target->str);
+ if (target->mergeable && part->mergeable &&
+ target->indent + target->str->len + 1 + part->str->len <= state->opts->max_line_length)
+ {
+ if (target->str->len > 0 && target->str->data[target->str->len - 1] != '(')
+ appendStringInfoChar(target->str, ' ');
+ appendStringInfoString(target->str, part->str->data);
+ freeDeparseStatePart(part);
+ part_group->parts = foreach_delete_current(part_group->parts, lc2);
+ }
+ else
+ {
+ target = part;
+ }
+ }
+ }
+
+ if (part_group->keyword != NULL)
+ {
+ DeparseStatePart *target = makeDeparseStatePart(state, level, false);
+ appendStringInfoString(target->str, part_group->keyword);
+ part_group->parts = list_insert_nth(part_group->parts, 0, target);
+
+ if (list_length(part_group->parts) == 2 || part_group->indent_mode == DEPARSE_PART_NO_INDENT)
+ {
+ DeparseStatePart *part = (DeparseStatePart *) lsecond(part_group->parts);
+ if (part->str->len > 0)
+ appendStringInfo(target->str, " %s", part->str->data);
+ freeDeparseStatePart(part);
+ part_group->parts = list_delete_nth_cell(part_group->parts, 1);
+ }
+ }
+
+ if (parent_level)
+ {
+ DeparseStatePartGroup *parent_part_group = (DeparseStatePartGroup *) llast(parent_level->part_groups);
+ parent_part_group->parts = list_concat(parent_part_group->parts, part_group->parts);
+ }
+ else
+ {
+ // If its the top level, save as results instead
+ state->result_parts = list_concat(state->result_parts, part_group->parts);
+ }
+
+ list_free(part_group->parts);
+ pfree(part_group);
+ }
+ list_free(level->part_groups);
+ pfree(level);
+
+ state->current = parent_level;
+
+ if (parent_level)
+ {
+ /* Make sure parent statement writes that follow are on their own line */
+ deparseAppendPart(state, true);
+
+ /* Parts with nested elements don't get merged, even if otherwise permitted */
+ deparseMarkCurrentPartNonMergable(state);
+ }
+}
+
+/*
+ * Append a SQL string literal representing "val" to buf.
+ *
+ * Copied here from postgres_fdw/deparse.c to avoid adding
+ * many additional dependencies, and modified to work with deparser
+ * state.
+ */
+static void
+deparseStringLiteral(DeparseState *state, const char *val)
+{
+ const char *valptr;
+
+ /*
+ * Rather than making assumptions about the remote server's value of
+ * standard_conforming_strings, always use E'foo' syntax if there are any
+ * backslashes. This will fail on remote servers before 8.1, but those
+ * are long out of support.
+ */
+ if (strchr(val, '\\') != NULL)
+ deparseAppendStringInfoChar(state, ESCAPE_STRING_SYNTAX);
+ deparseAppendStringInfoChar(state, '\'');
+ for (valptr = val; *valptr; valptr++)
+ {
+ char ch = *valptr;
+
+ if (SQL_STR_DOUBLE(ch, true))
+ deparseAppendStringInfoChar(state, ch);
+ deparseAppendStringInfoChar(state, ch);
+ }
+ deparseAppendStringInfoChar(state, '\'');
+}
+
+// "any_name" in gram.y
+static void deparseAnyName(DeparseState *state, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, parts)
+ {
+ Assert(IsA(lfirst(lc), String));
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ deparseAppendStringInfoChar(state, '.');
+ }
+}
+static void deparseAnyNameSkipFirst(DeparseState *state, List *parts)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, parts, 1)
+ {
+ Assert(IsA(lfirst(lc), String));
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(parts, lc))
+ deparseAppendStringInfoChar(state, '.');
+ }
+}
+static void deparseAnyNameSkipLast(DeparseState *state, List *parts)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, parts)
+ {
+ if (lnext(parts, lc))
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (foreach_current_index(lc) < list_length(parts) - 2)
+ deparseAppendStringInfoChar(state, '.');
+ }
+ }
+}
+
+// "func_expr" in gram.y
+static void deparseFuncExpr(DeparseState *state, Node *node, DeparseNodeContext context)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(state, castNode(FuncCall, node), context);
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(state, castNode(SQLValueFunction, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(state, castNode(MinMaxExpr, node));
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(state, castNode(CoalesceExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(state, castNode(XmlExpr, node), context);
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(state, castNode(XmlSerialize, node));
+ break;
+ case T_JsonObjectAgg:
+ deparseJsonObjectAgg(state, castNode(JsonObjectAgg, node));
+ break;
+ case T_JsonArrayAgg:
+ deparseJsonArrayAgg(state, castNode(JsonArrayAgg, node));
+ break;
+ case T_JsonObjectConstructor:
+ deparseJsonObjectConstructor(state, castNode(JsonObjectConstructor, node));
+ break;
+ case T_JsonArrayConstructor:
+ deparseJsonArrayConstructor(state, castNode(JsonArrayConstructor, node));
+ break;
+ case T_JsonArrayQueryConstructor:
+ deparseJsonArrayQueryConstructor(state, castNode(JsonArrayQueryConstructor, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in func_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+static void deparseCExpr(DeparseState *state, Node *node);
+
+// "a_expr" in gram.y
+static void deparseExpr(DeparseState *state, Node *node, DeparseNodeContext context)
+{
+ if (node == NULL)
+ return;
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ case T_A_Const:
+ case T_ParamRef:
+ case T_A_Indirection:
+ case T_CaseExpr:
+ case T_SubLink:
+ case T_A_ArrayExpr:
+ case T_RowExpr:
+ case T_GroupingFunc:
+ deparseCExpr(state, node);
+ break;
+ case T_TypeCast:
+ deparseTypeCast(state, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_CollateClause:
+ deparseCollateClause(state, castNode(CollateClause, node));
+ break;
+ case T_A_Expr:
+ deparseAExpr(state, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_A_EXPR);
+ break;
+ case T_BoolExpr:
+ deparseBoolExpr(state, castNode(BoolExpr, node));
+ break;
+ case T_NullTest:
+ deparseNullTest(state, castNode(NullTest, node));
+ break;
+ case T_BooleanTest:
+ deparseBooleanTest(state, castNode(BooleanTest, node));
+ break;
+ case T_JsonIsPredicate:
+ deparseJsonIsPredicate(state, castNode(JsonIsPredicate, node));
+ break;
+ case T_SetToDefault:
+ deparseSetToDefault(state, castNode(SetToDefault, node));
+ break;
+ case T_MergeSupportFunc:
+ deparseAppendStringInfoString(state, "merge_action() ");
+ break;
+ case T_JsonParseExpr:
+ deparseJsonParseExpr(state, castNode(JsonParseExpr, node));
+ break;
+ case T_JsonScalarExpr:
+ deparseJsonScalarExpr(state, castNode(JsonScalarExpr, node));
+ break;
+ case T_JsonSerializeExpr:
+ deparseJsonSerializeExpr(state, castNode(JsonSerializeExpr, node));
+ break;
+ case T_JsonFuncExpr:
+ deparseJsonFuncExpr(state, castNode(JsonFuncExpr, node));
+ break;
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_MinMaxExpr:
+ case T_CoalesceExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ case T_JsonObjectAgg:
+ case T_JsonArrayAgg:
+ case T_JsonObjectConstructor:
+ case T_JsonArrayConstructor:
+ case T_JsonArrayQueryConstructor:
+ deparseFuncExpr(state, node, context);
+ break;
+ default:
+ // Note that this is also the fallthrough for deparseBExpr and deparseCExpr
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr/c_expr: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "b_expr" in gram.y
+static void deparseBExpr(DeparseState *state, Node *node)
+{
+ if (IsA(node, XmlExpr)) {
+ deparseXmlExpr(state, castNode(XmlExpr, node), DEPARSE_NODE_CONTEXT_NONE);
+ return;
+ }
+
+ if (IsA(node, A_Expr)) {
+ A_Expr *a_expr = castNode(A_Expr, node);
+ // Other kinds are handled by "c_expr", with parens added around them
+ if (a_expr->kind == AEXPR_OP || a_expr->kind == AEXPR_DISTINCT || a_expr->kind == AEXPR_NOT_DISTINCT) {
+ deparseAExpr(state, a_expr, DEPARSE_NODE_CONTEXT_NONE);
+ return;
+ }
+ }
+
+ if (IsA(node, BoolExpr)) {
+ BoolExpr *bool_expr = castNode(BoolExpr, node);
+ if (bool_expr->boolop == NOT_EXPR) {
+ deparseBoolExpr(state, bool_expr);
+ return;
+ }
+ }
+
+ deparseCExpr(state, node);
+}
+
+// "AexprConst" in gram.y
+static void deparseAexprConst(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_A_Const:
+ deparseAConst(state, castNode(A_Const, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(state, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted node type in AexprConst: %d",
+ (int) nodeTag(node));
+ break;
+ }
+}
+
+// "c_expr" in gram.y
+static void deparseCExpr(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnRef:
+ deparseColumnRef(state, castNode(ColumnRef, node));
+ break;
+ case T_A_Const:
+ deparseAConst(state, castNode(A_Const, node));
+ break;
+ case T_ParamRef:
+ deparseParamRef(state, castNode(ParamRef, node));
+ break;
+ case T_A_Indirection:
+ deparseAIndirection(state, castNode(A_Indirection, node));
+ break;
+ case T_CaseExpr:
+ deparseCaseExpr(state, castNode(CaseExpr, node));
+ break;
+ case T_SubLink:
+ deparseSubLink(state, castNode(SubLink, node));
+ break;
+ case T_A_ArrayExpr:
+ deparseAArrayExpr(state, castNode(A_ArrayExpr, node));
+ break;
+ case T_RowExpr:
+ deparseRowExpr(state, castNode(RowExpr, node));
+ break;
+ case T_GroupingFunc:
+ deparseGroupingFunc(state, castNode(GroupingFunc, node));
+ break;
+ case T_FuncCall:
+ case T_SQLValueFunction:
+ case T_MinMaxExpr:
+ case T_CoalesceExpr:
+ case T_XmlExpr:
+ case T_XmlSerialize:
+ case T_JsonObjectAgg:
+ case T_JsonArrayAgg:
+ case T_JsonObjectConstructor:
+ case T_JsonArrayConstructor:
+ case T_JsonArrayQueryConstructor:
+ deparseFuncExpr(state, node, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ deparseAppendStringInfoChar(state, '(');
+ // Because we wrap this in parenthesis, the expression inside follows "a_expr" parser rules
+ deparseExpr(state, node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ }
+}
+
+// "expr_list" in gram.y
+static void deparseExprList(DeparseState *state, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseExpr(state, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (lnext(exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
+static void deparseColId(DeparseState *state, char *s)
+{
+ deparseAppendStringInfoString(state, quote_identifier(s));
+}
+
+// "ColLabel", "attr_name"
+//
+// Note this is kept separate from ColId in case we ever want to be more
+// specific on how to handle keywords here
+static void deparseColLabel(DeparseState *state, char *s)
+{
+ deparseAppendStringInfoString(state, quote_identifier(s));
+}
+
+// "SignedIconst" and "Iconst" in gram.y
+static void deparseSignedIconst(DeparseState *state, Node *node)
+{
+ deparseAppendStringInfo(state, "%d", intVal(node));
+}
+
+// "indirection" and "opt_indirection" in gram.y
+static void deparseOptIndirection(DeparseState *state, List *indirection, int N)
+{
+ ListCell *lc = NULL;
+
+ for_each_from(lc, indirection, N)
+ {
+ if (IsA(lfirst(lc), String))
+ {
+ deparseAppendStringInfoChar(state, '.');
+ deparseColLabel(state, strVal(lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Star))
+ {
+ deparseAppendStringInfoString(state, ".*");
+ }
+ else if (IsA(lfirst(lc), A_Indices))
+ {
+ deparseAIndices(state, castNode(A_Indices, lfirst(lc)));
+ }
+ else
+ {
+ // No other nodes should appear here
+ Assert(false);
+ }
+ }
+}
+
+// "role_list" in gram.y
+static void deparseRoleList(DeparseState *state, List *roles)
+{
+ ListCell *lc;
+
+ foreach(lc, roles)
+ {
+ RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
+ deparseRoleSpec(state, role_spec);
+ if (lnext(roles, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "SimpleTypename" in gram.y
+static void deparseSimpleTypename(DeparseState *state, Node *node)
+{
+ deparseTypeName(state, castNode(TypeName, node));
+}
+
+// "NumericOnly" in gram.y
+static void deparseNumericOnly(DeparseState *state, union ValUnion *value)
+{
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ deparseAppendStringInfo(state, "%d", value->ival.ival);
+ break;
+ case T_Float:
+ deparseAppendStringInfoString(state, value->sval.sval);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "NumericOnly_list" in gram.y
+static void deparseNumericOnlyList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseNumericOnly(state, (union ValUnion *) lfirst(lc));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "SeqOptElem" in gram.y
+static void deparseSeqOptElem(DeparseState *state, DefElem *def_elem)
+{
+ ListCell *lc;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ deparseAppendStringInfoString(state, "AS ");
+ deparseSimpleTypename(state, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cache") == 0)
+ {
+ deparseAppendStringInfoString(state, "CACHE ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "cycle") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NO CYCLE");
+ }
+ else if (strcmp(def_elem->defname, "increment") == 0)
+ {
+ deparseAppendStringInfoString(state, "INCREMENT ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "MAXVALUE ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NO MAXVALUE");
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "MINVALUE ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NO MINVALUE");
+ }
+ else if (strcmp(def_elem->defname, "owned_by") == 0)
+ {
+ deparseAppendStringInfoString(state, "OWNED BY ");
+ deparseAnyName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "sequence_name") == 0)
+ {
+ deparseAppendStringInfoString(state, "SEQUENCE NAME ");
+ deparseAnyName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "start") == 0)
+ {
+ deparseAppendStringInfoString(state, "START ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "RESTART ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "SeqOptList" in gram.y
+static void deparseSeqOptList(DeparseState *state, List *options)
+{
+ ListCell *lc;
+ Assert(list_length(options) > 0);
+ foreach (lc, options)
+ {
+ deparseSeqOptElem(state, castNode(DefElem, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "OptSeqOptList" in gram.y
+static void deparseOptSeqOptList(DeparseState *state, List *options)
+{
+ if (list_length(options) > 0)
+ deparseSeqOptList(state, options);
+}
+
+// "OptParenthesizedSeqOptList" in gram.y
+static void deparseOptParenthesizedSeqOptList(DeparseState *state, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseSeqOptList(state, options);
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+// "opt_drop_behavior" in gram.y
+static void deparseOptDropBehavior(DeparseState *state, DropBehavior behavior)
+{
+ switch (behavior)
+ {
+ case DROP_RESTRICT:
+ // Default
+ break;
+ case DROP_CASCADE:
+ deparseAppendStringInfoString(state, "CASCADE ");
+ break;
+ }
+}
+
+// "any_operator" in gram.y
+static void deparseAnyOperator(DeparseState *state, List *op)
+{
+ Assert(isOp(strVal(llast(op))));
+ if (list_length(op) == 2)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(op))));
+ deparseAppendStringInfoChar(state, '.');
+ deparseAppendStringInfoString(state, strVal(llast(op)));
+ }
+ else if (list_length(op) == 1)
+ {
+ deparseAppendStringInfoString(state, strVal(llast(op)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "qual_Op" and "qual_all_Op" in gram.y
+static void deparseQualOp(DeparseState *state, List *op)
+{
+ if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ deparseAppendStringInfoString(state, strVal(linitial(op)));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "OPERATOR(");
+ deparseAnyOperator(state, op);
+ deparseAppendStringInfoString(state, ")");
+ }
+}
+
+// "subquery_Op" in gram.y
+static void deparseSubqueryOp(DeparseState *state, List *op)
+{
+ if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
+ {
+ deparseAppendStringInfoString(state, "LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
+ {
+ deparseAppendStringInfoString(state, "NOT LIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
+ {
+ deparseAppendStringInfoString(state, "ILIKE");
+ }
+ else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
+ {
+ deparseAppendStringInfoString(state, "NOT ILIKE");
+ }
+ else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
+ {
+ deparseAppendStringInfoString(state, strVal(linitial(op)));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "OPERATOR(");
+ deparseAnyOperator(state, op);
+ deparseAppendStringInfoString(state, ")");
+ }
+}
+
+// Not present directly in gram.y (usually matched by ColLabel)
+static void deparseGenericDefElemName(DeparseState *state, const char *in)
+{
+ Assert(in != NULL);
+ char *val = pstrdup(in);
+ for (unsigned char *p = (unsigned char *) val; *p; p++)
+ *p = pg_toupper(*p);
+ deparseAppendStringInfoString(state, val);
+ pfree(val);
+}
+
+// "def_arg" and "operator_def_arg" in gram.y
+static void deparseDefArg(DeparseState *state, Node *arg, bool is_operator_def_arg)
+{
+ if (IsA(arg, TypeName)) // func_type
+ {
+ deparseTypeName(state, castNode(TypeName, arg));
+ }
+ else if (IsA(arg, List)) // qual_all_Op
+ {
+ List *l = castNode(List, arg);
+ Assert(list_length(l) == 1 || list_length(l) == 2);
+
+ // Schema qualified operator
+ if (list_length(l) == 2)
+ {
+ deparseAppendStringInfoString(state, "OPERATOR(");
+ deparseAnyOperator(state, l);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ else if (list_length(l) == 1)
+ {
+ deparseAppendStringInfoString(state, strVal(linitial(l)));
+ }
+ }
+ else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
+ {
+ deparseValue(state, (union ValUnion *) arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (IsA(arg, String))
+ {
+ char *s = strVal(arg);
+ if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) // NONE
+ {
+ deparseAppendStringInfoString(state, "NONE");
+ }
+ else if (isReservedKeyword(s)) // reserved_keyword
+ {
+ deparseAppendStringInfoString(state, s);
+ }
+ else // Sconst
+ {
+ deparseStringLiteral(state, s);
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "definition" in gram.y
+static void deparseDefinition(DeparseState *state, List *options)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoChar(state, '(');
+ foreach (lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL) {
+ deparseAppendStringInfoString(state, " = ");
+ deparseDefArg(state, def_elem->arg, false);
+ }
+
+ if (lnext(options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "opt_definition" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptDefinition(DeparseState *state, List *options)
+{
+ if (list_length(options) > 0)
+ {
+ deparseAppendStringInfoString(state, "WITH ");
+ deparseDefinition(state, options);
+ }
+}
+
+// "create_generic_options" in gram.y
+static void deparseCreateGenericOptions(DeparseState *state, List *options)
+{
+ ListCell *lc = NULL;
+
+ if (options == NULL)
+ return;
+
+ deparseAppendStringInfoString(state, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ if (lnext(options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ")");
+}
+
+// "common_func_opt_item" in gram.y
+static void deparseCommonFuncOptItem(DeparseState *state, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "strict") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "RETURNS NULL ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "strict") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "CALLED ON NULL INPUT");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
+ {
+ deparseAppendStringInfoString(state, "IMMUTABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
+ {
+ deparseAppendStringInfoString(state, "STABLE");
+ }
+ else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
+ {
+ deparseAppendStringInfoString(state, "VOLATILE");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "SECURITY DEFINER");
+ }
+ else if (strcmp(def_elem->defname, "security") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "SECURITY INVOKER");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOT LEAKPROOF");
+ }
+ else if (strcmp(def_elem->defname, "cost") == 0)
+ {
+ deparseAppendStringInfoString(state, "COST ");
+ deparseValue(state, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "rows") == 0)
+ {
+ deparseAppendStringInfoString(state, "ROWS ");
+ deparseValue(state, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (strcmp(def_elem->defname, "support") == 0)
+ {
+ deparseAppendStringInfoString(state, "SUPPORT ");
+ deparseAnyName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) // FunctionSetResetClause
+ {
+ deparseVariableSetStmt(state, castNode(VariableSetStmt, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "parallel") == 0)
+ {
+ deparseAppendStringInfoString(state, "PARALLEL ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(def_elem->arg)));
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "NonReservedWord_or_Sconst" in gram.y
+//
+// Note since both identifiers and string constants are allowed here, we
+// currently always return an identifier, except:
+//
+// 1) when the string is empty (since an empty identifier can't be scanned)
+// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
+static void deparseNonReservedWordOrSconst(DeparseState *state, const char *val)
+{
+ if (strlen(val) == 0)
+ deparseAppendStringInfoString(state, "''");
+ else if (strlen(val) >= NAMEDATALEN)
+ deparseStringLiteral(state, val);
+ else
+ deparseAppendStringInfoString(state, quote_identifier(val));
+}
+
+// "func_as" in gram.y
+static void deparseFuncAs(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ char *strval = strVal(lfirst(lc));
+ if (strstr(strval, "$$") == NULL)
+ {
+ deparseAppendStringInfoString(state, "$$");
+ deparseAppendStringInfoString(state, strval);
+ deparseAppendStringInfoString(state, "$$");
+ }
+ else
+ {
+ deparseStringLiteral(state, strval);
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "createfunc_opt_item" in gram.y
+static void deparseCreateFuncOptItem(DeparseState *state, DefElem *def_elem)
+{
+ ListCell *lc = NULL;
+
+ if (strcmp(def_elem->defname, "as") == 0)
+ {
+ deparseAppendStringInfoString(state, "AS ");
+ deparseFuncAs(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "language") == 0)
+ {
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "transform") == 0)
+ {
+ List *l = castNode(List, def_elem->arg);
+ deparseAppendStringInfoString(state, "TRANSFORM ");
+ foreach (lc, l)
+ {
+ deparseAppendStringInfoString(state, "FOR TYPE ");
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ else if (strcmp(def_elem->defname, "window") == 0)
+ {
+ deparseAppendStringInfoString(state, "WINDOW");
+ }
+ else
+ {
+ deparseCommonFuncOptItem(state, def_elem);
+ }
+}
+
+// "alter_generic_options" in gram.y
+static void deparseAlterGenericOptions(DeparseState *state, List *options)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "OPTIONS (");
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ switch (def_elem->defaction)
+ {
+ case DEFELEM_UNSPEC:
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ break;
+ case DEFELEM_SET:
+ deparseAppendStringInfoString(state, "SET ");
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ break;
+ case DEFELEM_ADD:
+ deparseAppendStringInfoString(state, "ADD ");
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ break;
+ case DEFELEM_DROP:
+ deparseAppendStringInfoString(state, "DROP ");
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ break;
+ }
+
+ if (lnext(options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+}
+
+// "func_name" in gram.y
+static void deparseFuncName(DeparseState *state, List *func_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, func_name)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(func_name, lc))
+ deparseAppendStringInfoChar(state, '.');
+ }
+}
+
+// "function_with_argtypes" in gram.y
+static void deparseFunctionWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc;
+ deparseFuncName(state, object_with_args->objname);
+
+ if (!object_with_args->args_unspecified)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(state, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+// "function_with_argtypes_list" in gram.y
+static void deparseFunctionWithArgtypesList(DeparseState *state, List *l)
+{
+ ListCell *lc;
+
+ foreach(lc, l)
+ {
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "operator_with_argtypes" in gram.y
+static void deparseOperatorWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
+{
+ deparseAnyOperator(state, object_with_args->objname);
+
+ Assert(list_length(object_with_args->objargs) == 2);
+ deparseAppendStringInfoChar(state, '(');
+ if (linitial(object_with_args->objargs) == NULL)
+ deparseAppendStringInfoString(state, "NONE");
+ else
+ deparseTypeName(state, castNode(TypeName, linitial(object_with_args->objargs)));
+ deparseAppendStringInfoString(state, ", ");
+ if (lsecond(object_with_args->objargs) == NULL)
+ deparseAppendStringInfoString(state, "NONE");
+ else
+ deparseTypeName(state, castNode(TypeName, lsecond(object_with_args->objargs)));
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "aggr_args" in gram.y
+static void deparseAggrArgs(DeparseState *state, List *aggr_args)
+{
+ Assert(list_length(aggr_args) == 2);
+
+ ListCell *lc = NULL;
+ List *args = linitial(aggr_args);
+ int order_by_pos = intVal(lsecond(aggr_args));
+
+ deparseAppendStringInfoChar(state, '(');
+ if (args == NULL)
+ {
+ deparseAppendStringInfoChar(state, '*');
+ }
+ else
+ {
+ foreach(lc, args)
+ {
+ if (foreach_current_index(lc) == order_by_pos)
+ {
+ if (foreach_current_index(lc) > 0)
+ deparseAppendStringInfoChar(state, ' ');
+ deparseAppendStringInfoString(state, "ORDER BY ");
+ }
+ else if (foreach_current_index(lc) > 0)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseFunctionParameter(state, castNode(FunctionParameter, lfirst(lc)));
+ }
+
+ // Repeat the last direct arg as a ordered arg to handle the
+ // simplification done by makeOrderedSetArgs in gram.y
+ if (order_by_pos == list_length(args))
+ {
+ deparseAppendStringInfoString(state, " ORDER BY ");
+ deparseFunctionParameter(state, castNode(FunctionParameter, llast(args)));
+ }
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "aggregate_with_argtypes" in gram.y
+static void deparseAggregateWithArgtypes(DeparseState *state, ObjectWithArgs *object_with_args)
+{
+ ListCell *lc = NULL;
+
+ deparseFuncName(state, object_with_args->objname);
+
+ deparseAppendStringInfoChar(state, '(');
+ if (object_with_args->objargs == NULL && object_with_args->objfuncargs == NULL)
+ {
+ deparseAppendStringInfoChar(state, '*');
+ }
+ else
+ {
+ List *objargs = object_with_args->objargs;
+ if (object_with_args->objfuncargs)
+ objargs = object_with_args->objfuncargs;
+
+ foreach(lc, objargs)
+ {
+ if (IsA(lfirst(lc), FunctionParameter))
+ deparseFunctionParameter(state, castNode(FunctionParameter, lfirst(lc)));
+ else
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(objargs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "columnList" in gram.y
+static void deparseColumnList(DeparseState *state, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(columns, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "opt_column_and_period_list" and "optionalPeriodName" in gram.y
+static void deparseColumnListWithPeriod(DeparseState *state, List *columns)
+{
+ ListCell *lc = NULL;
+ foreach(lc, columns)
+ {
+ bool not_last = lnext(columns, lc);
+ if (!not_last)
+ deparseAppendStringInfoString(state, "PERIOD ");
+
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+
+ if (not_last)
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "OptTemp" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptTemp(DeparseState *state, char relpersistence)
+{
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_PERMANENT:
+ // Default
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ deparseAppendStringInfoString(state, "UNLOGGED ");
+ break;
+ case RELPERSISTENCE_TEMP:
+ deparseAppendStringInfoString(state, "TEMPORARY ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+// "relation_expr_list" in gram.y
+static void deparseRelationExprList(DeparseState *state, List *relation_exprs)
+{
+ ListCell *lc = NULL;
+ foreach(lc, relation_exprs)
+ {
+ deparseRangeVar(state, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(relation_exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "handler_name" in gram.y
+static void deparseHandlerName(DeparseState *state, List *handler_name)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, handler_name)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc))));
+ if (lnext(handler_name, lc))
+ deparseAppendStringInfoChar(state, '.');
+ }
+}
+
+// "fdw_options" in gram.y
+static void deparseFdwOptions(DeparseState *state, List *fdw_options)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, fdw_options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "HANDLER ");
+ deparseHandlerName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NO HANDLER ");
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "VALIDATOR ");
+ deparseHandlerName(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NO VALIDATOR ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(fdw_options, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "type_list" in gram.y
+static void deparseTypeList(DeparseState *state, List *type_list)
+{
+ ListCell *lc = NULL;
+ foreach(lc, type_list)
+ {
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(type_list, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "opt_boolean_or_string" in gram.y
+static void deparseOptBooleanOrString(DeparseState *state, char *s)
+{
+ if (s == NULL)
+ return; // No value set
+ else if (strcmp(s, "true") == 0)
+ deparseAppendStringInfoString(state, "TRUE");
+ else if (strcmp(s, "false") == 0)
+ deparseAppendStringInfoString(state, "FALSE");
+ else if (strcmp(s, "on") == 0)
+ deparseAppendStringInfoString(state, "ON");
+ else if (strcmp(s, "off") == 0)
+ deparseAppendStringInfoString(state, "OFF");
+ else
+ deparseNonReservedWordOrSconst(state, s);
+}
+
+static void deparseOptBoolean(DeparseState *state, Node *node)
+{
+ if (node == NULL)
+ {
+ return;
+ }
+
+ switch (nodeTag(node))
+ {
+ case T_String:
+ deparseAppendStringInfo(state, " %s", strVal(node));
+ break;
+ case T_Integer:
+ deparseAppendStringInfo(state, " %d", intVal(node));
+ break;
+ case T_Boolean:
+ deparseAppendStringInfo(state, " %s", boolVal(node) ? "TRUE" : "FALSE");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+bool optBooleanValue(Node *node)
+{
+ if (node == NULL)
+ {
+ return true;
+ }
+
+ switch (nodeTag(node))
+ {
+ case T_String: {
+ // Longest valid string is "off\0"
+ char lower[4];
+ strncpy(lower, strVal(node), 4);
+ lower[3] = 0;
+
+ if (strcmp(lower, "on") == 0) {
+ return true;
+ } else if (strcmp(lower, "off") == 0) {
+ return false;
+ }
+
+ // No sane way to handle this.
+ return false;
+ }
+ case T_Integer:
+ return intVal(node) != 0;
+ case T_Boolean:
+ return boolVal(node);
+ default:
+ Assert(false);
+ return false;
+ }
+}
+
+// "var_name"
+//
+// Note this is kept separate from ColId in case we want to improve the
+// output of namespaced variable names
+static void deparseVarName(DeparseState *state, char *s)
+{
+ deparseColId(state, s);
+}
+
+// "var_list"
+static void deparseVarList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), ParamRef))
+ {
+ deparseParamRef(state, castNode(ParamRef, lfirst(lc)));
+ }
+ else if (IsA(lfirst(lc), A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, lfirst(lc));
+ if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
+ deparseNumericOnly(state, (union ValUnion *) &a_const->val);
+ else if (IsA(&a_const->val, String))
+ deparseOptBooleanOrString(state, strVal(&a_const->val));
+ else
+ Assert(false);
+ }
+ else if (IsA(lfirst(lc), TypeCast))
+ {
+ deparseTypeCast(state, castNode(TypeCast, lfirst(lc)), DEPARSE_NODE_CONTEXT_SET_STATEMENT);
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "transaction_mode_list" in gram.y
+static void deparseTransactionModeList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "transaction_isolation") == 0)
+ {
+ char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
+ deparseAppendStringInfoString(state, "ISOLATION LEVEL ");
+ if (strcmp(s, "read uncommitted") == 0)
+ deparseAppendStringInfoString(state, "READ UNCOMMITTED");
+ else if (strcmp(s, "read committed") == 0)
+ deparseAppendStringInfoString(state, "READ COMMITTED");
+ else if (strcmp(s, "repeatable read") == 0)
+ deparseAppendStringInfoString(state, "REPEATABLE READ");
+ else if (strcmp(s, "serializable") == 0)
+ deparseAppendStringInfoString(state, "SERIALIZABLE");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ deparseAppendStringInfoString(state, "READ ONLY");
+ }
+ else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ deparseAppendStringInfoString(state, "READ WRITE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
+ {
+ deparseAppendStringInfoString(state, "DEFERRABLE");
+ }
+ else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
+ {
+ deparseAppendStringInfoString(state, "NOT DEFERRABLE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "alter_identity_column_option_list" in gram.y
+static void deparseAlterIdentityColumnOptionList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "RESTART");
+ }
+ else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoString(state, "RESTART ");
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "generated") == 0)
+ {
+ deparseAppendStringInfoString(state, "SET GENERATED ");
+ if (def_elem->arg == NULL)
+ elog(ERROR, "deparse: missing argument for identity generation specification");
+ if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
+ deparseAppendStringInfoString(state, "ALWAYS");
+ else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+ deparseAppendStringInfoString(state, "BY DEFAULT");
+ else
+ Assert(false);
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "SET ");
+ deparseSeqOptElem(state, def_elem);
+ }
+ if (lnext(l, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "reloptions" in gram.y
+static void deparseRelOptions(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (def_elem->defnamespace != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defnamespace));
+ deparseAppendStringInfoChar(state, '.');
+ }
+ if (def_elem->defname != NULL)
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ if (def_elem->defname != NULL && def_elem->arg != NULL)
+ deparseAppendStringInfoChar(state, '=');
+ if (def_elem->arg != NULL)
+ deparseDefArg(state, def_elem->arg, false);
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+// "OptWith" and "opt_reloptions" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptWith(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ deparseAppendStringInfoString(state, "WITH ");
+ deparseRelOptions(state, l);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "target_list" and "opt_target_list" in gram.y
+static void deparseTargetList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+
+ if (res_target->val == NULL)
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
+ else if (IsA(res_target->val, ColumnRef))
+ deparseColumnRef(state, castNode(ColumnRef, res_target->val));
+ else
+ deparseExpr(state, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (res_target->name != NULL) {
+ deparseAppendStringInfoString(state, " AS ");
+ deparseAppendStringInfoString(state, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ deparseAppendCommaAndPart(state);
+ }
+}
+
+// "insert_column_list" in gram.y
+static void deparseInsertColumnList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->name != NULL);
+ deparseAppendStringInfoString(state, quote_identifier(res_target->name));
+ deparseOptIndirection(state, res_target->indirection, 0);
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "xml_attribute_list" in gram.y
+static void deparseXmlAttributeList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ deparseExpr(state, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (res_target->name != NULL)
+ {
+ deparseAppendStringInfoString(state, " AS ");
+ deparseAppendStringInfoString(state, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "xml_namespace_list" in gram.y
+static void deparseXmlNamespaceList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (res_target->name == NULL)
+ deparseAppendStringInfoString(state, "DEFAULT ");
+
+ deparseExpr(state, res_target->val, DEPARSE_NODE_CONTEXT_NONE /* b_expr */);
+
+ if (res_target->name != NULL)
+ {
+ deparseAppendStringInfoString(state, " AS ");
+ deparseAppendStringInfoString(state, quote_identifier(res_target->name));
+ }
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "table_ref" in gram.y
+static void deparseTableRef(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_RangeVar:
+ deparseRangeVar(state, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_RangeTableSample:
+ deparseRangeTableSample(state, castNode(RangeTableSample, node));
+ break;
+ case T_RangeFunction:
+ deparseRangeFunction(state, castNode(RangeFunction, node));
+ break;
+ case T_RangeTableFunc:
+ deparseRangeTableFunc(state, castNode(RangeTableFunc, node));
+ break;
+ case T_RangeSubselect:
+ deparseRangeSubselect(state, castNode(RangeSubselect, node));
+ break;
+ case T_JoinExpr:
+ deparseJoinExpr(state, castNode(JoinExpr, node));
+ break;
+ case T_JsonTable:
+ deparseJsonTable(state, castNode(JsonTable, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "from_list" in gram.y
+static void deparseFromList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseTableRef(state, lfirst(lc));
+ if (lnext(l, lc))
+ deparseAppendCommaAndPart(state);
+ }
+}
+
+// "from_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseFromClause(DeparseState *state, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ deparseAppendPartGroup(state, "FROM", DEPARSE_PART_INDENT);
+ deparseFromList(state, l);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "where_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereClause(DeparseState *state, Node *node)
+{
+ if (node != NULL)
+ {
+ deparseAppendPartGroup(state, "WHERE", DEPARSE_PART_INDENT);
+ deparseExpr(state, node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "where_or_current_clause" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseWhereOrCurrentClause(DeparseState *state, Node *node)
+{
+ if (node == NULL)
+ return;
+
+ deparseAppendPartGroup(state, "WHERE", DEPARSE_PART_INDENT);
+
+ if (IsA(node, CurrentOfExpr)) {
+ CurrentOfExpr *current_of_expr = castNode(CurrentOfExpr, node);
+ deparseAppendStringInfoString(state, "CURRENT OF ");
+ deparseAppendStringInfoString(state, quote_identifier(current_of_expr->cursor_name));
+ } else {
+ deparseExpr(state, node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+}
+
+// "group_by_list" in gram.y
+static void deparseGroupByList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ if (IsA(lfirst(lc), GroupingSet))
+ deparseGroupingSet(state, castNode(GroupingSet, lfirst(lc)));
+ else
+ deparseExpr(state, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (lnext(l, lc))
+ deparseAppendCommaAndPart(state);
+ }
+}
+
+// "set_target" in gram.y
+static void deparseSetTarget(DeparseState *state, ResTarget *res_target)
+{
+ Assert(res_target->name != NULL);
+ deparseColId(state, res_target->name);
+ deparseOptIndirection(state, res_target->indirection, 0);
+}
+
+// "any_name_list" in gram.y
+static void deparseAnyNameList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseAnyName(state, castNode(List, lfirst(lc)));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "name_list" in gram.y
+static void deparseNameList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseColId(state, strVal(lfirst(lc)));
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "opt_sort_clause" and "json_array_aggregate_order_by_clause_opt" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptSortClause(DeparseState *state, List *l, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+
+ if (list_length(l) > 0)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_SELECT_SORT_CLAUSE)
+ deparseAppendPartGroup(state, "ORDER BY", DEPARSE_PART_INDENT_AND_MERGE);
+ else
+ deparseAppendStringInfoString(state, "ORDER BY ");
+
+ foreach(lc, l)
+ {
+ deparseSortBy(state, castNode(SortBy, lfirst(lc)));
+ if (lnext(l, lc))
+ {
+ if (context == DEPARSE_NODE_CONTEXT_SELECT_SORT_CLAUSE)
+ deparseAppendCommaAndPart(state);
+ else
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "func_arg_expr" in gram.y
+static void deparseFuncArgExpr(DeparseState *state, Node *node)
+{
+ if (IsA(node, NamedArgExpr))
+ {
+ NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
+ deparseAppendStringInfoString(state, named_arg_expr->name);
+ deparseAppendStringInfoString(state, " := ");
+ deparseExpr(state, (Node *) named_arg_expr->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ else
+ {
+ deparseExpr(state, node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+}
+
+// "set_clause_list" in gram.y
+static void deparseSetClauseList(DeparseState *state, List *target_list)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ int skip_next_n_elems = 0;
+
+ Assert(list_length(target_list) > 0);
+
+ foreach(lc, target_list)
+ {
+ if (skip_next_n_elems > 0)
+ {
+ skip_next_n_elems--;
+ continue;
+ }
+
+ if (foreach_current_index(lc) != 0)
+ deparseAppendCommaAndPart(state);
+
+ ResTarget *res_target = castNode(ResTarget, lfirst(lc));
+ Assert(res_target->val != NULL);
+
+ if (IsA(res_target->val, MultiAssignRef))
+ {
+ MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
+ deparseAppendStringInfoString(state, "(");
+ for_each_cell(lc2, target_list, lc)
+ {
+ deparseSetTarget(state, castNode(ResTarget, lfirst(lc2)));
+ if ((foreach_current_index(lc2) - foreach_current_index(lc)) == r->ncolumns - 1) // Last element in this multi-assign
+ break;
+ else if (lnext(target_list, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") = ");
+ deparseExpr(state, r->source, DEPARSE_NODE_CONTEXT_A_EXPR);
+ skip_next_n_elems = r->ncolumns - 1;
+ }
+ else
+ {
+ deparseSetTarget(state, res_target);
+ deparseAppendStringInfoString(state, " = ");
+ deparseExpr(state, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ }
+}
+
+// "func_expr_windowless" in gram.y
+static void deparseFuncExprWindowless(DeparseState *state, Node* node)
+{
+ switch (nodeTag(node))
+ {
+ case T_FuncCall:
+ deparseFuncCall(state, castNode(FuncCall, node), DEPARSE_NODE_CONTEXT_NONE /* we don't know which kind of expression */);
+ break;
+ case T_SQLValueFunction:
+ deparseSQLValueFunction(state, castNode(SQLValueFunction, node));
+ break;
+ case T_TypeCast:
+ deparseTypeCast(state, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_FUNC_EXPR);
+ break;
+ case T_CoalesceExpr:
+ deparseCoalesceExpr(state, castNode(CoalesceExpr, node));
+ break;
+ case T_MinMaxExpr:
+ deparseMinMaxExpr(state, castNode(MinMaxExpr, node));
+ break;
+ case T_XmlExpr:
+ deparseXmlExpr(state, castNode(XmlExpr, node), DEPARSE_NODE_CONTEXT_NONE /* we don't know which kind of expression */);
+ break;
+ case T_XmlSerialize:
+ deparseXmlSerialize(state, castNode(XmlSerialize, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "opt_collate" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptCollate(DeparseState *state, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ deparseAppendStringInfoString(state, "COLLATE ");
+ deparseAnyName(state, l);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "index_elem" in gram.y
+static void deparseIndexElem(DeparseState *state, IndexElem* index_elem)
+{
+ if (index_elem->name != NULL)
+ {
+ deparseColId(state, index_elem->name);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (index_elem->expr != NULL)
+ {
+ switch (nodeTag(index_elem->expr))
+ {
+ // Simple function calls can be written without wrapping parens
+ case T_FuncCall: // func_application
+ case T_SQLValueFunction: // func_expr_common_subexpr
+ case T_CoalesceExpr: // func_expr_common_subexpr
+ case T_MinMaxExpr: // func_expr_common_subexpr
+ case T_XmlExpr: // func_expr_common_subexpr
+ case T_XmlSerialize: // func_expr_common_subexpr
+ deparseFuncExprWindowless(state, index_elem->expr);
+ deparseAppendStringInfoString(state, " ");
+ break;
+ default:
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, index_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseOptCollate(state, index_elem->collation);
+
+ if (list_length(index_elem->opclass) > 0)
+ {
+ deparseAnyName(state, index_elem->opclass);
+
+ if (list_length(index_elem->opclassopts) > 0)
+ deparseRelOptions(state, index_elem->opclassopts);
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (index_elem->ordering)
+ {
+ case SORTBY_DEFAULT:
+ // Default
+ break;
+ case SORTBY_ASC:
+ deparseAppendStringInfoString(state, "ASC ");
+ break;
+ case SORTBY_DESC:
+ deparseAppendStringInfoString(state, "DESC ");
+ break;
+ case SORTBY_USING:
+ // Not allowed in CREATE INDEX
+ Assert(false);
+ break;
+ }
+
+ switch (index_elem->nulls_ordering)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ // Default
+ break;
+ case SORTBY_NULLS_FIRST:
+ deparseAppendStringInfoString(state, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ deparseAppendStringInfoString(state, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "qualified_name_list" in gram.y
+static void deparseQualifiedNameList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach(lc, l)
+ {
+ deparseRangeVar(state, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ if (lnext(l, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "OptInherit" in gram.y
+//
+// Note this method adds a trailing space if a value is output
+static void deparseOptInherit(DeparseState *state, List *l)
+{
+ if (list_length(l) > 0)
+ {
+ deparseAppendStringInfoString(state, "INHERITS (");
+ deparseQualifiedNameList(state, l);
+ deparseAppendStringInfoString(state, ") ");
+ }
+}
+
+// "privilege_target" in gram.y
+static void deparsePrivilegeTarget(DeparseState *state, GrantTargetType targtype, ObjectType objtype, List *objs)
+{
+ switch (targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseQualifiedNameList(state, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ deparseQualifiedNameList(state, objs);
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "FOREIGN SERVER ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypesList(state, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypesList(state, objs);
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypesList(state, objs);
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ deparseAnyNameList(state, objs);
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECT ");
+ deparseNumericOnlyList(state, objs);
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseAnyNameList(state, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "ALL TABLES IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "ALL SEQUENCES IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "ALL FUNCTIONS IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "ALL PROCEDURES IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ALL ROUTINES IN SCHEMA ");
+ deparseNameList(state, objs);
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ case ACL_TARGET_DEFAULTS: // defacl_privilege_target
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLES");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTIONS");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCES");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPES");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMAS");
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECTS");
+ break;
+ default:
+ // Other types are not supported here
+ Assert(false);
+ break;
+ }
+ break;
+ }
+}
+
+// "opclass_item_list" in gram.y
+static void deparseOpclassItemList(DeparseState *state, List *items)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, items)
+ {
+ deparseCreateOpClassItem(state, castNode(CreateOpClassItem, lfirst(lc)));
+ if (lnext(items, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+// "createdb_opt_list" in gram.y
+static void deparseCreatedbOptList(DeparseState *state, List *l)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, l)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "connection_limit") == 0)
+ deparseAppendStringInfoString(state, "CONNECTION LIMIT");
+ else
+ deparseGenericDefElemName(state, def_elem->defname);
+
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (def_elem->arg == NULL)
+ deparseAppendStringInfoString(state, "DEFAULT");
+ else if (IsA(def_elem->arg, Integer))
+ deparseSignedIconst(state, def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(state, strVal(def_elem->arg));
+
+ if (lnext(l, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+// "utility_option_list" in gram.y
+static void deparseUtilityOptionList(DeparseState *state, List *options)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ if (list_length(options) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseGenericDefElemName(state, def_elem->defname);
+
+ if (def_elem->arg != NULL)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ else if (IsA(def_elem->arg, String))
+ deparseOptBooleanOrString(state, strVal(def_elem->arg));
+ else
+ Assert(false);
+ }
+
+ if (lnext(options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+}
+
+static void deparseSelectStmt(DeparseState *state, SelectStmt *stmt, DeparseNodeContext context)
+{
+ const ListCell *lc = NULL;
+ const ListCell *lc2 = NULL;
+ bool need_parens = context == DEPARSE_NODE_CONTEXT_SELECT_SETOP && (
+ list_length(stmt->sortClause) > 0 ||
+ stmt->limitOffset != NULL ||
+ stmt->limitCount != NULL ||
+ list_length(stmt->lockingClause) > 0 ||
+ stmt->withClause != NULL ||
+ stmt->op != SETOP_NONE);
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ if (need_parens)
+ {
+ deparseAppendPart(state, true);
+ deparseAppendStringInfoChar(state, '(');
+ }
+ if (need_parens || (context != DEPARSE_NODE_CONTEXT_SELECT_SETOP && context != DEPARSE_NODE_CONTEXT_INSERT_SELECT))
+ parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (stmt->withClause)
+ {
+ deparseWithClause(state, stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (stmt->op) {
+ case SETOP_NONE:
+ if (list_length(stmt->valuesLists) > 0)
+ {
+ const ListCell *lc;
+ deparseAppendPartGroup(state, "VALUES", DEPARSE_PART_INDENT_AND_MERGE);
+
+ foreach(lc, stmt->valuesLists)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseExprList(state, lfirst(lc));
+ deparseAppendStringInfoChar(state, ')');
+ if (lnext(stmt->valuesLists, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ }
+
+ deparseAppendPartGroup(state, "SELECT", DEPARSE_PART_INDENT_AND_MERGE);
+
+ if (list_length(stmt->targetList) > 0)
+ {
+ if (stmt->distinctClause != NULL)
+ {
+ deparseMarkCurrentPartNonMergable(state);
+ deparseAppendStringInfoString(state, "DISTINCT ");
+
+ if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
+ {
+ deparseAppendStringInfoString(state, "ON (");
+ deparseExprList(state, stmt->distinctClause);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ deparseAppendPart(state, true);
+ }
+
+ deparseTargetList(state, stmt->targetList);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (stmt->intoClause != NULL)
+ {
+ deparseAppendPartGroup(state, "INTO", DEPARSE_PART_INDENT);
+ deparseOptTemp(state, stmt->intoClause->rel->relpersistence);
+ deparseIntoClause(state, stmt->intoClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseFromClause(state, stmt->fromClause);
+ deparseWhereClause(state, stmt->whereClause);
+
+ if (list_length(stmt->groupClause) > 0)
+ {
+ deparseAppendPartGroup(state, "GROUP BY", DEPARSE_PART_INDENT_AND_MERGE);
+ if (stmt->groupDistinct)
+ deparseAppendStringInfoString(state, "DISTINCT ");
+ deparseGroupByList(state, stmt->groupClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (stmt->havingClause != NULL)
+ {
+ deparseAppendPartGroup(state, "HAVING", DEPARSE_PART_INDENT);
+ deparseExpr(state, stmt->havingClause, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (stmt->windowClause != NULL)
+ {
+ deparseAppendPartGroup(state, "WINDOW", DEPARSE_PART_INDENT);
+ foreach(lc, stmt->windowClause)
+ {
+ WindowDef *window_def = castNode(WindowDef, lfirst(lc));
+ Assert(window_def->name != NULL);
+ deparseAppendStringInfoString(state, window_def->name);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseWindowDef(state, window_def);
+ if (lnext(stmt->windowClause, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ break;
+ case SETOP_UNION:
+ case SETOP_INTERSECT:
+ case SETOP_EXCEPT:
+ {
+ deparseSelectStmt(state, stmt->larg, DEPARSE_NODE_CONTEXT_SELECT_SETOP);
+ switch (stmt->op)
+ {
+ case SETOP_UNION:
+ if (stmt->all)
+ deparseAppendPartGroup(state, "UNION ALL", DEPARSE_PART_NO_INDENT);
+ else
+ deparseAppendPartGroup(state, "UNION", DEPARSE_PART_NO_INDENT);
+ break;
+ case SETOP_INTERSECT:
+ if (stmt->all)
+ deparseAppendPartGroup(state, "INTERSECT ALL", DEPARSE_PART_NO_INDENT);
+ else
+ deparseAppendPartGroup(state, "INTERSECT", DEPARSE_PART_NO_INDENT);
+ break;
+ case SETOP_EXCEPT:
+ if (stmt->all)
+ deparseAppendPartGroup(state, "EXCEPT ALL", DEPARSE_PART_NO_INDENT);
+ else
+ deparseAppendPartGroup(state, "EXCEPT", DEPARSE_PART_NO_INDENT);
+ break;
+ default:
+ Assert(false);
+ }
+ deparseAppendPart(state, true);
+ deparseSelectStmt(state, stmt->rarg, DEPARSE_NODE_CONTEXT_SELECT_SETOP);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ break;
+ }
+
+ deparseOptSortClause(state, stmt->sortClause, DEPARSE_NODE_CONTEXT_SELECT_SORT_CLAUSE);
+
+ if (stmt->limitCount != NULL)
+ {
+ if (stmt->limitOption == LIMIT_OPTION_COUNT)
+ deparseAppendPartGroup(state, "LIMIT", DEPARSE_PART_INDENT);
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ deparseAppendStringInfoString(state, "FETCH FIRST ");
+
+ if (IsA(stmt->limitCount, A_Const) && castNode(A_Const, stmt->limitCount)->isnull)
+ deparseAppendStringInfoString(state, "ALL");
+ else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ deparseCExpr(state, stmt->limitCount);
+ else
+ deparseExpr(state, stmt->limitCount, DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
+ deparseAppendStringInfoString(state, "ROWS WITH TIES ");
+ }
+
+ if (stmt->limitOffset != NULL)
+ {
+ deparseAppendPartGroup(state, "OFFSET", DEPARSE_PART_INDENT);
+ deparseExpr(state, stmt->limitOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(stmt->lockingClause) > 0)
+ {
+ foreach(lc, stmt->lockingClause)
+ {
+ deparseLockingClause(state, castNode(LockingClause, lfirst(lc)));
+ if (lnext(stmt->lockingClause, lc))
+ deparseAppendStringInfoString(state, " ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+
+ /* Note that parent_level can be NULL, so we repeat the full if condition here */
+ if (need_parens || (context != DEPARSE_NODE_CONTEXT_SELECT_SETOP && context != DEPARSE_NODE_CONTEXT_INSERT_SELECT))
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseIntoClause(DeparseState *state, IntoClause *into_clause)
+{
+ ListCell *lc;
+
+ deparseRangeVar(state, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE); /* target relation name */
+
+ if (list_length(into_clause->colNames) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, into_clause->colNames);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (into_clause->accessMethod != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(into_clause->accessMethod));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseOptWith(state, into_clause->options);
+
+ switch (into_clause->onCommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ deparseAppendStringInfoString(state, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ deparseAppendStringInfoString(state, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ deparseAppendStringInfoString(state, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (into_clause->tableSpaceName != NULL)
+ {
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseAppendStringInfoString(state, quote_identifier(into_clause->tableSpaceName));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseRangeVar(DeparseState *state, RangeVar *range_var, DeparseNodeContext context)
+{
+ if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ deparseAppendStringInfoString(state, "ONLY ");
+
+ if (range_var->catalogname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(range_var->catalogname));
+ deparseAppendStringInfoChar(state, '.');
+ }
+
+ if (range_var->schemaname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(range_var->schemaname));
+ deparseAppendStringInfoChar(state, '.');
+ }
+
+ Assert(range_var->relname != NULL);
+ deparseAppendStringInfoString(state, quote_identifier(range_var->relname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (range_var->alias != NULL)
+ {
+ if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
+ deparseAppendStringInfoString(state, "AS ");
+ deparseAlias(state, range_var->alias);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+void deparseRawStmt(StringInfo str, struct RawStmt *raw_stmt)
+{
+ PostgresDeparseOpts opts;
+ MemSet(&opts, 0, sizeof(PostgresDeparseOpts)); // zero initialized means pretty print = false
+ deparseRawStmtOpts(str, raw_stmt, &opts);
+}
+
+void deparseRawStmtOpts(StringInfo str, struct RawStmt *raw_stmt, PostgresDeparseOpts *opts)
+{
+ DeparseState *state = NULL;
+ if (raw_stmt->stmt == NULL)
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
+
+ state = palloc0(sizeof(DeparseState));
+ state->opts = opts;
+ if (state->opts->indent_size == 0)
+ state->opts->indent_size = 4;
+ if (state->opts->max_line_length == 0)
+ state->opts->max_line_length = 80;
+
+ /* Check for any comments at the start of the statement */
+ if (state->opts->comment_count > 0)
+ {
+ deparseStateIncreaseNestingLevel(state);
+ deparseAppendCommentsIfNeeded(state, raw_stmt->stmt_location);
+ deparseRemoveTrailingEmptyPart(state);
+ deparseStateDecreaseNestingLevel(state, NULL);
+ }
+
+ deparseStmt(state, raw_stmt->stmt);
+
+ /* Check for any comments at the end of the statement */
+ if (state->opts->comment_count > 0)
+ {
+ deparseStateIncreaseNestingLevel(state);
+ deparseAppendCommentsIfNeeded(state, INT_MAX);
+ deparseRemoveTrailingEmptyPart(state);
+ deparseStateDecreaseNestingLevel(state, NULL);
+ }
+
+ deparseEmit(state, str);
+
+ bms_free(state->emitted_comments);
+ pfree(state);
+}
+
+static void deparseAlias(DeparseState *state, Alias *alias)
+{
+ deparseAppendStringInfoString(state, quote_identifier(alias->aliasname));
+
+ if (list_length(alias->colnames) > 0)
+ {
+ const ListCell *lc = NULL;
+ deparseAppendStringInfoChar(state, '(');
+ deparseNameList(state, alias->colnames);
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+static void deparseAConst(DeparseState *state, A_Const *a_const)
+{
+ union ValUnion *val = a_const->isnull ? NULL : &a_const->val;
+ deparseAppendCommentsIfNeeded(state, a_const->location);
+ deparseValue(state, val, DEPARSE_NODE_CONTEXT_CONSTANT);
+}
+
+static void deparseFuncCall(DeparseState *state, FuncCall *func_call, DeparseNodeContext context)
+{
+ const ListCell *lc = NULL;
+
+ Assert(list_length(func_call->funcname) > 0);
+
+ if (list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ deparseAppendStringInfoString(state, "OVERLAY(");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " PLACING ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseExpr(state, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FOR ");
+ deparseExpr(state, lfourth(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "substring") == 0)
+ {
+ /*
+ * "SUBSTRING" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.substring)
+ */
+ Assert(list_length(func_call->args) == 2 || list_length(func_call->args) == 3);
+ deparseAppendStringInfoString(state, "SUBSTRING(");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (list_length(func_call->args) == 3)
+ {
+ deparseAppendStringInfoString(state, " FOR ");
+ deparseExpr(state, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "position") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "POSITION" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.position)
+ * Note that the first and second arguments are switched in this format
+ */
+ deparseAppendStringInfoString(state, "POSITION(");
+ deparseBExpr(state, lsecond(func_call->args));
+ deparseAppendStringInfoString(state, " IN ");
+ deparseBExpr(state, linitial(func_call->args));
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
+ list_length(func_call->args) == 3)
+ {
+ /*
+ * "OVERLAY" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ deparseAppendStringInfoString(state, "overlay(");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " placing ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " from ");
+ deparseExpr(state, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "pg_collation_for") == 0 &&
+ list_length(func_call->args) == 1)
+ {
+ /*
+ * "collation for" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
+ */
+ deparseAppendStringInfoString(state, "collation for (");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "extract") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ /*
+ * "EXTRACT" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.extract)
+ */
+ deparseAppendStringInfoString(state, "extract (");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "overlaps") == 0 &&
+ list_length(func_call->args) == 4)
+ {
+ /*
+ * "OVERLAPS" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlaps)
+ * format: (start_1, end_1) overlaps (start_2, end_2)
+ */
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+
+ deparseAppendStringInfoString(state, "overlaps ");
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, lfourth(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ (
+ strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0 ||
+ strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0
+ ))
+ {
+ /*
+ * "TRIM " is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.ltrim)
+ * Note that the first and second arguments are switched in this format
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ deparseAppendStringInfoString(state, "TRIM (");
+ if (strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0)
+ deparseAppendStringInfoString(state, "LEADING ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0)
+ deparseAppendStringInfoString(state, "BOTH ");
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0)
+ deparseAppendStringInfoString(state, "TRAILING ");
+
+ if (list_length(func_call->args) == 2)
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "timezone") == 0 &&
+ list_length(func_call->args) > 0 &&
+ list_length(func_call->args) <= 2)
+ {
+ /*
+ * "AT TIME ZONE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.timezone)
+ * Note that the arguments are swapped in this case
+ */
+ Expr* e;
+ bool isLocal = list_length(func_call->args) == 1;
+
+ if (isLocal)
+ e = linitial(func_call->args);
+ else
+ e = lsecond(func_call->args);
+
+ // If we're not inside an a_expr context, we must add wrapping parenthesis around the AT ... syntax
+ if (context != DEPARSE_NODE_CONTEXT_A_EXPR) {
+ deparseAppendStringInfoChar(state, '(');
+ }
+
+ if (IsA(e, A_Expr)) {
+ deparseAppendStringInfoChar(state, '(');
+ }
+
+ deparseExpr(state, (Node*) e, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (IsA(e, A_Expr)) {
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ if (isLocal)
+ deparseAppendStringInfoString(state, " AT LOCAL");
+ else {
+ deparseAppendStringInfoString(state, " AT TIME ZONE ");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+
+ if (context != DEPARSE_NODE_CONTEXT_A_EXPR) {
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "normalize") == 0)
+ {
+ /*
+ * "NORMALIZE" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.normalize)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+ deparseAppendStringInfoString(state, "normalize (");
+
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (list_length(func_call->args) == 2)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(state, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "is_normalized") == 0)
+ {
+ /*
+ * "IS NORMALIZED" is a keyword on its own merit, and only accepts the
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.is_normalized)
+ */
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
+
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " IS ");
+ if (list_length(func_call->args) == 2)
+ {
+ Assert(IsA(lsecond(func_call->args), A_Const));
+ A_Const *aconst = lsecond(func_call->args);
+ deparseValue(state, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ deparseAppendStringInfoString(state, " NORMALIZED ");
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "xmlexists") == 0 &&
+ list_length(func_call->args) == 2)
+ {
+ deparseAppendStringInfoString(state, "xmlexists (");
+ deparseExpr(state, linitial(func_call->args), DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+ deparseAppendStringInfoString(state, " PASSING ");
+ deparseExpr(state, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
+ list_length(func_call->funcname) == 2 &&
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
+ strcmp(strVal(lsecond(func_call->funcname)), "system_user") == 0)
+ {
+ deparseAppendStringInfoString(state, "SYSTEM_USER");
+ return;
+ }
+
+ deparseFuncName(state, func_call->funcname);
+ deparseAppendStringInfoChar(state, '(');
+
+ if (func_call->agg_distinct)
+ deparseAppendStringInfoString(state, "DISTINCT ");
+
+ if (func_call->agg_star)
+ {
+ deparseAppendStringInfoChar(state, '*');
+ }
+ else if (list_length(func_call->args) > 0)
+ {
+ foreach(lc, func_call->args)
+ {
+ if (func_call->func_variadic && !lnext(func_call->args, lc))
+ deparseAppendStringInfoString(state, "VARIADIC ");
+ deparseFuncArgExpr(state, lfirst(lc));
+ if (lnext(func_call->args, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (func_call->agg_order != NULL && !func_call->agg_within_group)
+ {
+ deparseOptSortClause(state, func_call->agg_order, DEPARSE_NODE_CONTEXT_NONE);
+ }
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (func_call->agg_order != NULL && func_call->agg_within_group)
+ {
+ deparseAppendStringInfoString(state, "WITHIN GROUP (");
+ deparseOptSortClause(state, func_call->agg_order, DEPARSE_NODE_CONTEXT_NONE);
+ removeTrailingSpace(state);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (func_call->agg_filter)
+ {
+ deparseAppendStringInfoString(state, "FILTER (WHERE ");
+ deparseExpr(state, func_call->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (func_call->over)
+ {
+ deparseAppendStringInfoString(state, "OVER ");
+ if (func_call->over->name)
+ deparseAppendStringInfoString(state, func_call->over->name);
+ else
+ deparseWindowDef(state, func_call->over);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseWindowDef(DeparseState *state, WindowDef* window_def)
+{
+ ListCell *lc;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ // The parent node is responsible for outputting window_def->name
+
+ // Special case completely empty window clauses and return early
+ if (!window_def->refname && list_length(window_def->partitionClause) == 0 &&
+ list_length(window_def->orderClause) == 0 &&
+ !(window_def->frameOptions & FRAMEOPTION_NONDEFAULT))
+ {
+ deparseAppendStringInfoString(state, "()");
+ return;
+ }
+
+ deparseAppendStringInfoChar(state, '(');
+ parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (window_def->refname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(window_def->refname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(window_def->partitionClause) > 0)
+ {
+ deparseAppendStringInfoString(state, "PARTITION BY ");
+ deparseExprList(state, window_def->partitionClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+ deparseAppendPart(state, true);
+ deparseOptSortClause(state, window_def->orderClause, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
+ {
+ deparseAppendPartGroup(state, NULL, DEPARSE_PART_NO_INDENT);
+ if (window_def->frameOptions & FRAMEOPTION_RANGE)
+ deparseAppendStringInfoString(state, "RANGE ");
+ else if (window_def->frameOptions & FRAMEOPTION_ROWS)
+ deparseAppendStringInfoString(state, "ROWS ");
+ else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
+ deparseAppendStringInfoString(state, "GROUPS ");
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ deparseAppendStringInfoString(state, "BETWEEN ");
+
+ // frame_start
+ if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ {
+ deparseAppendStringInfoString(state, "UNBOUNDED PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
+ {
+ deparseAppendStringInfoString(state, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(state, window_def->startOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->startOffset != NULL);
+ deparseExpr(state, window_def->startOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FOLLOWING ");
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
+ {
+ deparseAppendStringInfoString(state, "AND ");
+
+ // frame_end
+ if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
+ {
+ Assert(false); // disallowed
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
+ {
+ deparseAppendStringInfoString(state, "UNBOUNDED FOLLOWING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
+ {
+ deparseAppendStringInfoString(state, "CURRENT ROW ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(state, window_def->endOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " PRECEDING ");
+ }
+ else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
+ {
+ Assert(window_def->endOffset != NULL);
+ deparseExpr(state, window_def->endOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " FOLLOWING ");
+ }
+ }
+
+ if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
+ deparseAppendStringInfoString(state, "EXCLUDE CURRENT ROW ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
+ deparseAppendStringInfoString(state, "EXCLUDE GROUP ");
+ else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
+ deparseAppendStringInfoString(state, "EXCLUDE TIES ");
+ }
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseColumnRef(DeparseState *state, ColumnRef* column_ref)
+{
+ Assert(list_length(column_ref->fields) >= 1);
+
+ deparseAppendCommentsIfNeeded(state, column_ref->location);
+
+ if (IsA(linitial(column_ref->fields), A_Star))
+ deparseAStar(state, castNode(A_Star, linitial(column_ref->fields)));
+ else if (IsA(linitial(column_ref->fields), String))
+ deparseColLabel(state, strVal(linitial(column_ref->fields)));
+
+ deparseOptIndirection(state, column_ref->fields, 1);
+}
+
+static void deparseSubLink(DeparseState *state, SubLink* sub_link)
+{
+ switch (sub_link->subLinkType) {
+ case EXISTS_SUBLINK:
+ deparseAppendStringInfoString(state, "EXISTS (");
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case ALL_SUBLINK:
+ deparseExpr(state, sub_link->testexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseSubqueryOp(state, sub_link->operName);
+ deparseAppendStringInfoString(state, " ALL (");
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case ANY_SUBLINK:
+ deparseExpr(state, sub_link->testexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (list_length(sub_link->operName) > 0)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseSubqueryOp(state, sub_link->operName);
+ deparseAppendStringInfoString(state, " ANY ");
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, " IN ");
+ }
+ deparseAppendStringInfoChar(state, '(');
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case ROWCOMPARE_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case EXPR_SUBLINK:
+ deparseAppendStringInfoString(state, "(");
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case MULTIEXPR_SUBLINK:
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ case ARRAY_SUBLINK:
+ deparseAppendStringInfoString(state, "ARRAY(");
+ deparseSelectStmt(state, castNode(SelectStmt, sub_link->subselect), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case CTE_SUBLINK: /* for SubPlans only */
+ // Not present in raw parse trees
+ Assert(false);
+ return;
+ }
+}
+
+// Checks whether a node needs parens when used in a "b_expr" context (because the node is handled by the "a_expr" rule in gram.y)
+static bool
+needsParensAsBExpr(Node *node)
+{
+ if (node == NULL)
+ return false;
+ return IsA(node, BoolExpr) || IsA(node, BooleanTest) || IsA(node, NullTest) || IsA(node, A_Expr);
+}
+
+// This handles "A_Expr" parse tree objects, which are a subset of the rules in "a_expr" (handled by deparseExpr)
+static void deparseAExpr(DeparseState *state, A_Expr* a_expr, DeparseNodeContext context)
+{
+ ListCell *lc;
+ char *name;
+
+ bool need_lexpr_parens = needsParensAsBExpr(a_expr->lexpr);
+ bool need_rexpr_parens = needsParensAsBExpr(a_expr->rexpr);
+
+ switch (a_expr->kind) {
+ case AEXPR_OP: /* normal operator */
+ {
+ if (a_expr->lexpr != NULL)
+ {
+ if (need_lexpr_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, a_expr->lexpr, context);
+ if (need_lexpr_parens)
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ deparseQualOp(state, a_expr->name);
+ if (a_expr->rexpr != NULL)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ if (need_rexpr_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, a_expr->rexpr, context);
+ if (need_rexpr_parens)
+ deparseAppendStringInfoChar(state, ')');
+ }
+ }
+ return;
+ case AEXPR_OP_ANY: /* scalar op ANY (array) */
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseSubqueryOp(state, a_expr->name);
+ deparseAppendStringInfoString(state, " ANY(");
+ deparseExpr(state, a_expr->rexpr, context);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_OP_ALL: /* scalar op ALL (array) */
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseSubqueryOp(state, a_expr->name);
+ deparseAppendStringInfoString(state, " ALL(");
+ deparseExpr(state, a_expr->rexpr, context);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ if (need_lexpr_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, a_expr->lexpr, context);
+ if (need_lexpr_parens)
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoString(state, " IS DISTINCT FROM ");
+ if (need_rexpr_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, a_expr->rexpr, context);
+ if (need_rexpr_parens)
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoString(state, " IS NOT DISTINCT FROM ");
+ deparseExpr(state, a_expr->rexpr, context);
+ return;
+ case AEXPR_NULLIF: /* NULLIF - name must be "=" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
+
+ deparseAppendStringInfoString(state, "NULLIF(");
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, a_expr->rexpr, context);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "=") == 0) {
+ deparseAppendStringInfoString(state, "IN ");
+ } else if (strcmp(name, "<>") == 0) {
+ deparseAppendStringInfoString(state, "NOT IN ");
+ } else {
+ Assert(false);
+ }
+ deparseAppendStringInfoChar(state, '(');
+ if (IsA(a_expr->rexpr, SubLink))
+ deparseSubLink(state, castNode(SubLink, a_expr->rexpr));
+ else
+ deparseExprList(state, castNode(List, a_expr->rexpr));
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~~") == 0) {
+ deparseAppendStringInfoString(state, "LIKE ");
+ } else if (strcmp(name, "!~~") == 0) {
+ deparseAppendStringInfoString(state, "NOT LIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(state, a_expr->rexpr, context);
+ return;
+ case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~~*") == 0) {
+ deparseAppendStringInfoString(state, "ILIKE ");
+ } else if (strcmp(name, "!~~*") == 0) {
+ deparseAppendStringInfoString(state, "NOT ILIKE ");
+ } else {
+ Assert(false);
+ }
+
+ deparseExpr(state, a_expr->rexpr, context);
+ return;
+ case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
+ if (strcmp(name, "~") == 0) {
+ deparseAppendStringInfoString(state, "SIMILAR TO ");
+ } else if (strcmp(name, "!~") == 0) {
+ deparseAppendStringInfoString(state, "NOT SIMILAR TO ");
+ } else {
+ Assert(false);
+ }
+
+ FuncCall *n = castNode(FuncCall, a_expr->rexpr);
+ Assert(list_length(n->funcname) == 2);
+ Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
+ Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
+ Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
+
+ deparseExpr(state, linitial(n->args), context);
+ if (list_length(n->args) == 2)
+ {
+ deparseAppendStringInfoString(state, " ESCAPE ");
+ deparseExpr(state, lsecond(n->args), context);
+ }
+
+ return;
+ case AEXPR_BETWEEN: /* name must be "BETWEEN" */
+ case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
+ case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
+ case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
+ Assert(list_length(a_expr->name) == 1);
+ Assert(IsA(linitial(a_expr->name), String));
+ Assert(IsA(a_expr->rexpr, List));
+
+ deparseExpr(state, a_expr->lexpr, context);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseAppendStringInfoString(state, strVal(linitial(a_expr->name)));
+ deparseAppendStringInfoChar(state, ' ');
+
+ foreach(lc, castNode(List, a_expr->rexpr)) {
+ deparseExpr(state, lfirst(lc), context);
+ if (lnext(castNode(List, a_expr->rexpr), lc))
+ deparseAppendStringInfoString(state, " AND ");
+ }
+ return;
+ }
+}
+
+static void deparseBoolExpr(DeparseState *state, BoolExpr *bool_expr)
+{
+ const ListCell *lc = NULL;
+ switch (bool_expr->boolop)
+ {
+ case AND_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseExpr(state, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ if (lnext(bool_expr->args, lc))
+ {
+ deparseAppendPart(state, true);
+ deparseAppendStringInfoString(state, "AND ");
+ }
+ }
+ return;
+ case OR_EXPR:
+ foreach(lc, bool_expr->args)
+ {
+ // Put parantheses around AND + OR nodes that are inside
+ bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseExpr(state, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ if (lnext(bool_expr->args, lc))
+ deparseAppendStringInfoString(state, " OR ");
+ }
+ return;
+ case NOT_EXPR:
+ Assert(list_length(bool_expr->args) == 1);
+ bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
+ deparseAppendStringInfoString(state, "NOT ");
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, linitial(bool_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ }
+}
+
+static void deparseAStar(DeparseState *state, A_Star *a_star)
+{
+ deparseAppendStringInfoChar(state, '*');
+}
+
+static void deparseCollateClause(DeparseState *state, CollateClause* collate_clause)
+{
+ ListCell *lc;
+ if (collate_clause->arg != NULL)
+ {
+ bool need_parens = IsA(collate_clause->arg, A_Expr);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, collate_clause->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ deparseAppendStringInfoString(state, "COLLATE ");
+ deparseAnyName(state, collate_clause->collname);
+}
+
+// "sortby" in gram.y
+static void deparseSortBy(DeparseState *state, SortBy* sort_by)
+{
+ deparseExpr(state, sort_by->node, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (sort_by->sortby_dir)
+ {
+ case SORTBY_DEFAULT:
+ break;
+ case SORTBY_ASC:
+ deparseAppendStringInfoString(state, "ASC ");
+ break;
+ case SORTBY_DESC:
+ deparseAppendStringInfoString(state, "DESC ");
+ break;
+ case SORTBY_USING:
+ deparseAppendStringInfoString(state, "USING ");
+ deparseQualOp(state, sort_by->useOp);
+ break;
+ }
+
+ switch (sort_by->sortby_nulls)
+ {
+ case SORTBY_NULLS_DEFAULT:
+ break;
+ case SORTBY_NULLS_FIRST:
+ deparseAppendStringInfoString(state, "NULLS FIRST ");
+ break;
+ case SORTBY_NULLS_LAST:
+ deparseAppendStringInfoString(state, "NULLS LAST ");
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseParamRef(DeparseState *state, ParamRef* param_ref)
+{
+ if (param_ref->number == 0) {
+ deparseAppendStringInfoChar(state, '?');
+ } else {
+ deparseAppendStringInfo(state, "$%d", param_ref->number);
+ }
+}
+
+static void deparseSQLValueFunction(DeparseState *state, SQLValueFunction* sql_value_function)
+{
+ switch (sql_value_function->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ deparseAppendStringInfoString(state, "current_date");
+ break;
+ case SVFOP_CURRENT_TIME:
+ deparseAppendStringInfoString(state, "current_time");
+ break;
+ case SVFOP_CURRENT_TIME_N:
+ deparseAppendStringInfoString(state, "current_time"); // with precision
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ deparseAppendStringInfoString(state, "current_timestamp");
+ break;
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ deparseAppendStringInfoString(state, "current_timestamp"); // with precision
+ break;
+ case SVFOP_LOCALTIME:
+ deparseAppendStringInfoString(state, "localtime");
+ break;
+ case SVFOP_LOCALTIME_N:
+ deparseAppendStringInfoString(state, "localtime"); // with precision
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ deparseAppendStringInfoString(state, "localtimestamp");
+ break;
+ case SVFOP_LOCALTIMESTAMP_N:
+ deparseAppendStringInfoString(state, "localtimestamp"); // with precision
+ break;
+ case SVFOP_CURRENT_ROLE:
+ deparseAppendStringInfoString(state, "current_role");
+ break;
+ case SVFOP_CURRENT_USER:
+ deparseAppendStringInfoString(state, "current_user");
+ break;
+ case SVFOP_USER:
+ deparseAppendStringInfoString(state, "user");
+ break;
+ case SVFOP_SESSION_USER:
+ deparseAppendStringInfoString(state, "session_user");
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ deparseAppendStringInfoString(state, "current_catalog");
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ deparseAppendStringInfoString(state, "current_schema");
+ break;
+ }
+
+ if (sql_value_function->typmod != -1)
+ {
+ deparseAppendStringInfo(state, "(%d)", sql_value_function->typmod);
+ }
+}
+
+static void deparseWithClause(DeparseState *state, WithClause *with_clause)
+{
+ ListCell *lc;
+
+ deparseAppendPartGroup(state, "WITH", DEPARSE_PART_NO_INDENT);
+ if (with_clause->recursive)
+ deparseAppendStringInfoString(state, "RECURSIVE ");
+
+ foreach(lc, with_clause->ctes) {
+ deparseCommonTableExpr(state, castNode(CommonTableExpr, lfirst(lc)));
+ if (lnext(with_clause->ctes, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "joined_table" in gram.y
+static void deparseJoinExpr(DeparseState *state, JoinExpr *join_expr)
+{
+ ListCell *lc;
+ bool need_alias_parens = join_expr->alias != NULL;
+ bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
+
+ if (need_alias_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseTableRef(state, join_expr->larg);
+ deparseAppendPart(state, true);
+
+ if (join_expr->isNatural)
+ deparseAppendStringInfoString(state, "NATURAL ");
+
+ switch (join_expr->jointype)
+ {
+ case JOIN_INNER: /* matching tuple pairs only */
+ if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
+ deparseAppendStringInfoString(state, "CROSS ");
+ break;
+ case JOIN_LEFT: /* pairs + unmatched LHS tuples */
+ deparseAppendStringInfoString(state, "LEFT ");
+ break;
+ case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
+ deparseAppendStringInfoString(state, "FULL ");
+ break;
+ case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
+ deparseAppendStringInfoString(state, "RIGHT ");
+ break;
+ case JOIN_SEMI:
+ case JOIN_ANTI:
+ case JOIN_RIGHT_SEMI:
+ case JOIN_RIGHT_ANTI:
+ case JOIN_UNIQUE_OUTER:
+ case JOIN_UNIQUE_INNER:
+ // Only used by the planner/executor, not seen in parser output
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "JOIN ");
+
+ if (need_rarg_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseTableRef(state, join_expr->rarg);
+ if (need_rarg_parens)
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (join_expr->quals != NULL)
+ {
+ deparseAppendStringInfoString(state, "ON ");
+ deparseExpr(state, join_expr->quals, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(join_expr->usingClause) > 0)
+ {
+ deparseAppendStringInfoString(state, "USING (");
+ deparseNameList(state, join_expr->usingClause);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (join_expr->join_using_alias)
+ {
+ deparseAppendStringInfoString(state, "AS ");
+ deparseAppendStringInfoString(state, join_expr->join_using_alias->aliasname);
+ }
+ }
+
+ if (need_alias_parens)
+ deparseAppendStringInfoString(state, ") ");
+
+ if (join_expr->alias != NULL)
+ deparseAlias(state, join_expr->alias);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCTESearchClause(DeparseState *state, CTESearchClause *search_clause)
+{
+ deparseAppendStringInfoString(state, " SEARCH ");
+ if (search_clause->search_breadth_first)
+ deparseAppendStringInfoString(state, "BREADTH ");
+ else
+ deparseAppendStringInfoString(state, "DEPTH ");
+
+ deparseAppendStringInfoString(state, "FIRST BY ");
+
+ if (search_clause->search_col_list)
+ deparseColumnList(state, search_clause->search_col_list);
+
+ deparseAppendStringInfoString(state, " SET ");
+ deparseAppendStringInfoString(state, quote_identifier(search_clause->search_seq_column));
+}
+
+// "opt_cycle_clause" in gram.y
+static void deparseCTECycleClause(DeparseState *state, CTECycleClause *cycle_clause)
+{
+ deparseAppendStringInfoString(state, " CYCLE ");
+
+ if (cycle_clause->cycle_col_list)
+ deparseColumnList(state, cycle_clause->cycle_col_list);
+
+ deparseAppendStringInfoString(state, " SET ");
+ deparseAppendStringInfoString(state, quote_identifier(cycle_clause->cycle_mark_column));
+
+ if (cycle_clause->cycle_mark_value)
+ {
+ deparseAppendStringInfoString(state, " TO ");
+ deparseAexprConst(state, cycle_clause->cycle_mark_value);
+ }
+
+ if (cycle_clause->cycle_mark_default)
+ {
+ deparseAppendStringInfoString(state, " DEFAULT ");
+ deparseAexprConst(state, cycle_clause->cycle_mark_default);
+ }
+
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(cycle_clause->cycle_path_column));
+}
+
+static void deparseCommonTableExpr(DeparseState *state, CommonTableExpr *cte)
+{
+ deparseAppendCommentsIfNeeded(state, cte->location);
+
+ deparseColId(state, cte->ctename);
+
+ if (list_length(cte->aliascolnames) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseNameList(state, cte->aliascolnames);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "AS ");
+ switch (cte->ctematerialized) {
+ case CTEMaterializeDefault: /* no option specified */
+ break;
+ case CTEMaterializeAlways:
+ deparseAppendStringInfoString(state, "MATERIALIZED ");
+ break;
+ case CTEMaterializeNever:
+ deparseAppendStringInfoString(state, "NOT MATERIALIZED ");
+ break;
+ }
+
+ deparseAppendStringInfoChar(state, '(');
+ deparsePreparableStmt(state, cte->ctequery);
+ deparseAppendStringInfoChar(state, ')');
+
+ if (cte->search_clause)
+ deparseCTESearchClause(state, cte->search_clause);
+ if (cte->cycle_clause)
+ deparseCTECycleClause(state, cte->cycle_clause);
+}
+
+static void deparseRangeSubselect(DeparseState *state, RangeSubselect *range_subselect)
+{
+ if (range_subselect->lateral)
+ deparseAppendStringInfoString(state, "LATERAL ");
+
+ deparseAppendStringInfoChar(state, '(');
+ deparseSelectStmt(state, castNode(SelectStmt, range_subselect->subquery), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ')');
+
+ if (range_subselect->alias != NULL)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseAlias(state, range_subselect->alias);
+ }
+}
+
+static void deparseRangeFunction(DeparseState *state, RangeFunction *range_func)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ if (range_func->lateral)
+ deparseAppendStringInfoString(state, "LATERAL ");
+
+ if (range_func->is_rowsfrom)
+ {
+ deparseAppendStringInfoString(state, "ROWS FROM ");
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, range_func->functions)
+ {
+ List *lfunc = castNode(List, lfirst(lc));
+ Assert(list_length(lfunc) == 2);
+ deparseFuncExprWindowless(state, linitial(lfunc));
+ deparseAppendStringInfoChar(state, ' ');
+ List *coldeflist = castNode(List, lsecond(lfunc));
+ if (list_length(coldeflist) > 0)
+ {
+ deparseAppendStringInfoString(state, "AS (");
+ foreach(lc2, coldeflist)
+ {
+ deparseColumnDef(state, castNode(ColumnDef, lfirst(lc2)));
+ if (lnext(coldeflist, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+ if (lnext(range_func->functions, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+ else
+ {
+ Assert(list_length(linitial(range_func->functions)) == 2);
+ deparseFuncExprWindowless(state, linitial(linitial(range_func->functions)));
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (range_func->ordinality)
+ deparseAppendStringInfoString(state, "WITH ORDINALITY ");
+
+ if (range_func->alias != NULL)
+ {
+ deparseAlias(state, range_func->alias);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(range_func->coldeflist) > 0)
+ {
+ if (range_func->alias == NULL)
+ deparseAppendStringInfoString(state, "AS ");
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, range_func->coldeflist)
+ {
+ deparseColumnDef(state, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(range_func->coldeflist, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAArrayExpr(DeparseState *state, A_ArrayExpr *array_expr)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ARRAY[");
+ deparseExprList(state, array_expr->elements);
+ deparseAppendStringInfoChar(state, ']');
+}
+
+static void deparseRowExpr(DeparseState *state, RowExpr *row_expr)
+{
+ ListCell *lc;
+
+ switch (row_expr->row_format)
+ {
+ case COERCE_EXPLICIT_CALL:
+ deparseAppendStringInfoString(state, "ROW");
+ break;
+ case COERCE_SQL_SYNTAX:
+ case COERCE_EXPLICIT_CAST:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCE_IMPLICIT_CAST:
+ // No prefix
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "(");
+ deparseExprList(state, row_expr->args);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseTypeCast(DeparseState *state, TypeCast *type_cast, DeparseNodeContext context)
+{
+ bool need_parens = needsParensAsBExpr(type_cast->arg);
+
+ Assert(type_cast->typeName != NULL);
+
+ if (context == DEPARSE_NODE_CONTEXT_FUNC_EXPR)
+ {
+ deparseAppendStringInfoString(state, "CAST(");
+ deparseExpr(state, type_cast->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, type_cast->typeName);
+ deparseAppendStringInfoChar(state, ')');
+ return;
+ }
+
+ if (IsA(type_cast->arg, A_Const))
+ {
+ A_Const *a_const = castNode(A_Const, type_cast->arg);
+
+ if (list_length(type_cast->typeName->names) == 2 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
+ {
+ char *typename = strVal(lsecond(type_cast->typeName->names));
+ if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
+ {
+ deparseAppendStringInfoString(state, "char ");
+ deparseAConst(state, a_const);
+ return;
+ }
+ else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
+ {
+ /*
+ * Handle "bool" or "false" in the statement, which is represented as a typecast
+ * (other boolean casts should be represented as a cast, i.e. don't need special handling)
+ */
+ char *const_val = strVal(&a_const->val);
+ if (strcmp(const_val, "t") == 0)
+ {
+ deparseAppendStringInfoString(state, "true");
+ return;
+ }
+ if (strcmp(const_val, "f") == 0)
+ {
+ deparseAppendStringInfoString(state, "false");
+ return;
+ }
+ }
+ else if (strcmp(typename, "interval") == 0 && context == DEPARSE_NODE_CONTEXT_SET_STATEMENT && IsA(&a_const->val, String))
+ {
+ deparseAppendStringInfoString(state, "interval ");
+ deparseAConst(state, a_const);
+ deparseIntervalTypmods(state, type_cast->typeName);
+ return;
+ }
+ }
+
+ // Ensure negative values have wrapping parentheses
+ if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
+ {
+ need_parens = true;
+ }
+
+ if (list_length(type_cast->typeName->names) == 1 &&
+ strcmp(strVal(linitial(type_cast->typeName->names)), "point") == 0 &&
+ a_const->location > type_cast->typeName->location)
+ {
+ deparseAppendStringInfoString(state, " point ");
+ deparseAConst(state, a_const);
+ return;
+ }
+ }
+
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, type_cast->arg, DEPARSE_NODE_CONTEXT_NONE /* could be either a_expr or b_expr (we could pass this down, but that'd require two kinds of contexts most likely) */);
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ deparseAppendStringInfoString(state, "::");
+ deparseTypeName(state, type_cast->typeName);
+}
+
+static void deparseTypeName(DeparseState *state, TypeName *type_name)
+{
+ ListCell *lc;
+ bool skip_typmods = false;
+
+ if (type_name->setof)
+ deparseAppendStringInfoString(state, "SETOF ");
+
+ if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
+ {
+ const char *name = strVal(lsecond(type_name->names));
+ if (strcmp(name, "bpchar") == 0)
+ {
+ deparseAppendStringInfoString(state, "char");
+ }
+ else if (strcmp(name, "varchar") == 0)
+ {
+ deparseAppendStringInfoString(state, "varchar");
+ }
+ else if (strcmp(name, "numeric") == 0)
+ {
+ deparseAppendStringInfoString(state, "numeric");
+ }
+ else if (strcmp(name, "bool") == 0)
+ {
+ deparseAppendStringInfoString(state, "boolean");
+ }
+ else if (strcmp(name, "int2") == 0)
+ {
+ deparseAppendStringInfoString(state, "smallint");
+ }
+ else if (strcmp(name, "int4") == 0)
+ {
+ deparseAppendStringInfoString(state, "int");
+ }
+ else if (strcmp(name, "int8") == 0)
+ {
+ deparseAppendStringInfoString(state, "bigint");
+ }
+ else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
+ {
+ deparseAppendStringInfoString(state, "real");
+ }
+ else if (strcmp(name, "float8") == 0)
+ {
+ deparseAppendStringInfoString(state, "double precision");
+ }
+ else if (strcmp(name, "time") == 0)
+ {
+ deparseAppendStringInfoString(state, "time");
+ }
+ else if (strcmp(name, "timetz") == 0)
+ {
+ deparseAppendStringInfoString(state, "time ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(state, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ deparseAppendStringInfoString(state, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "timestamp") == 0)
+ {
+ deparseAppendStringInfoString(state, "timestamp");
+ }
+ else if (strcmp(name, "timestamptz") == 0)
+ {
+ deparseAppendStringInfoString(state, "timestamp ");
+ if (list_length(type_name->typmods) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, type_name->typmods)
+ {
+ deparseSignedIconst(state, (Node *) &castNode(A_Const, lfirst(lc))->val);
+ if (lnext(type_name->typmods, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ deparseAppendStringInfoString(state, "with time zone");
+ skip_typmods = true;
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
+ {
+ deparseAppendStringInfoString(state, "interval");
+ }
+ else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
+ {
+ deparseAppendStringInfoString(state, "interval");
+ deparseIntervalTypmods(state, type_name);
+
+ skip_typmods = true;
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "pg_catalog.");
+ deparseAppendStringInfoString(state, name);
+ }
+ }
+ else
+ {
+ deparseAnyName(state, type_name->names);
+ }
+
+ if (list_length(type_name->typmods) > 0 && !skip_typmods)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, type_name->typmods)
+ {
+ if (IsA(lfirst(lc), A_Const))
+ deparseAConst(state, lfirst(lc));
+ else if (IsA(lfirst(lc), ParamRef))
+ deparseParamRef(state, lfirst(lc));
+ else if (IsA(lfirst(lc), ColumnRef))
+ deparseColumnRef(state, lfirst(lc));
+ else
+ Assert(false);
+
+ if (lnext(type_name->typmods, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ foreach(lc, type_name->arrayBounds)
+ {
+ deparseAppendStringInfoChar(state, '[');
+ if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
+ deparseSignedIconst(state, lfirst(lc));
+ deparseAppendStringInfoChar(state, ']');
+ }
+
+ if (type_name->pct_type)
+ deparseAppendStringInfoString(state, "%type");
+}
+
+// Handle typemods for Interval types separately
+// so that they can be applied appropriately for different contexts.
+// For example, when using `SET` a query like `INTERVAL 'x' hour TO minute`
+// the `INTERVAL` keyword is specified first.
+// In all other contexts, intervals use the `'x'::interval` style.
+static void deparseIntervalTypmods(DeparseState *state, TypeName *type_name)
+{
+ const char *name = strVal(lsecond(type_name->names));
+ Assert(strcmp(name, "interval") == 0);
+ Assert(list_length(type_name->typmods) >= 1);
+ Assert(IsA(linitial(type_name->typmods), A_Const));
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
+
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
+
+ // This logic is based on intervaltypmodout in timestamp.c
+ switch (fields)
+ {
+ case INTERVAL_MASK(YEAR):
+ deparseAppendStringInfoString(state, " year");
+ break;
+ case INTERVAL_MASK(MONTH):
+ deparseAppendStringInfoString(state, " month");
+ break;
+ case INTERVAL_MASK(DAY):
+ deparseAppendStringInfoString(state, " day");
+ break;
+ case INTERVAL_MASK(HOUR):
+ deparseAppendStringInfoString(state, " hour");
+ break;
+ case INTERVAL_MASK(MINUTE):
+ deparseAppendStringInfoString(state, " minute");
+ break;
+ case INTERVAL_MASK(SECOND):
+ deparseAppendStringInfoString(state, " second");
+ break;
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+ deparseAppendStringInfoString(state, " year to month");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+ deparseAppendStringInfoString(state, " day to hour");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ deparseAppendStringInfoString(state, " day to minute");
+ break;
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ deparseAppendStringInfoString(state, " day to second");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+ deparseAppendStringInfoString(state, " hour to minute");
+ break;
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ deparseAppendStringInfoString(state, " hour to second");
+ break;
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+ deparseAppendStringInfoString(state, " minute to second");
+ break;
+ case INTERVAL_FULL_RANGE:
+ // Nothing
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (list_length(type_name->typmods) == 2)
+ {
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
+ if (precision != INTERVAL_FULL_PRECISION)
+ deparseAppendStringInfo(state, "(%d)", precision);
+ }
+}
+
+static void deparseNullTest(DeparseState *state, NullTest *null_test)
+{
+ // argisrow is always false in raw parser output
+ Assert(null_test->argisrow == false);
+
+ deparseExpr(state, (Node *) null_test->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ switch (null_test->nulltesttype)
+ {
+ case IS_NULL:
+ deparseAppendStringInfoString(state, " IS NULL");
+ break;
+ case IS_NOT_NULL:
+ deparseAppendStringInfoString(state, " IS NOT NULL");
+ break;
+ }
+}
+
+// "case_expr" in gram.y
+static void deparseCaseExpr(DeparseState *state, CaseExpr *case_expr)
+{
+ ListCell *lc;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ deparseAppendStringInfoString(state, "CASE ");
+
+ if (case_expr->arg != NULL)
+ {
+ deparseExpr(state, (Node *) case_expr->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ parent_level = deparseStateIncreaseNestingLevel(state);
+
+ foreach(lc, case_expr->args)
+ {
+ deparseCaseWhen(state, castNode(CaseWhen, lfirst(lc)));
+ }
+
+ if (case_expr->defresult != NULL)
+ {
+ deparseAppendPartGroup(state, "ELSE", DEPARSE_PART_INDENT);
+ deparseExpr(state, (Node *) case_expr->defresult, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ deparseStateDecreaseNestingLevel(state, parent_level);
+
+ deparseAppendStringInfoString(state, "END");
+}
+
+// "when_clause" in gram.y
+static void deparseCaseWhen(DeparseState *state, CaseWhen *case_when)
+{
+ deparseAppendPartGroup(state, "WHEN", DEPARSE_PART_INDENT);
+ deparseExpr(state, (Node *) case_when->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " THEN ");
+ deparseExpr(state, (Node *) case_when->result, DEPARSE_NODE_CONTEXT_A_EXPR);
+}
+
+static void deparseAIndirection(DeparseState *state, A_Indirection *a_indirection)
+{
+ ListCell *lc;
+ bool need_parens =
+ IsA(a_indirection->arg, A_Indirection) ||
+ IsA(a_indirection->arg, FuncCall) ||
+ IsA(a_indirection->arg, A_Expr) ||
+ IsA(a_indirection->arg, TypeCast) ||
+ IsA(a_indirection->arg, RowExpr) ||
+ IsA(a_indirection->arg, A_ArrayExpr) ||
+ (IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices)) ||
+ IsA(a_indirection->arg, JsonFuncExpr);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseExpr(state, a_indirection->arg, need_parens ? DEPARSE_NODE_CONTEXT_A_EXPR : DEPARSE_NODE_CONTEXT_NONE);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ deparseOptIndirection(state, a_indirection->indirection, 0);
+}
+
+static void deparseAIndices(DeparseState *state, A_Indices *a_indices)
+{
+ deparseAppendStringInfoChar(state, '[');
+ if (a_indices->lidx != NULL)
+ deparseExpr(state, a_indices->lidx, DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (a_indices->is_slice)
+ deparseAppendStringInfoChar(state, ':');
+ if (a_indices->uidx != NULL)
+ deparseExpr(state, a_indices->uidx, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ']');
+}
+
+static void deparseCoalesceExpr(DeparseState *state, CoalesceExpr *coalesce_expr)
+{
+ deparseAppendStringInfoString(state, "COALESCE(");
+ deparseExprList(state, coalesce_expr->args);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseMinMaxExpr(DeparseState *state, MinMaxExpr *min_max_expr)
+{
+ switch (min_max_expr->op)
+ {
+ case IS_GREATEST:
+ deparseAppendStringInfoString(state, "GREATEST(");
+ break;
+ case IS_LEAST:
+ deparseAppendStringInfoString(state, "LEAST(");
+ break;
+ }
+ deparseExprList(state, min_max_expr->args);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseBooleanTest(DeparseState *state, BooleanTest *boolean_test)
+{
+ bool need_parens = IsA(boolean_test->arg, BoolExpr);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ deparseExpr(state, (Node *) boolean_test->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (need_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ switch (boolean_test->booltesttype)
+ {
+ case IS_TRUE:
+ deparseAppendStringInfoString(state, " IS TRUE");
+ break;
+ case IS_NOT_TRUE:
+ deparseAppendStringInfoString(state, " IS NOT TRUE");
+ break;
+ case IS_FALSE:
+ deparseAppendStringInfoString(state, " IS FALSE");
+ break;
+ case IS_NOT_FALSE:
+ deparseAppendStringInfoString(state, " IS NOT FALSE");
+ break;
+ case IS_UNKNOWN:
+ deparseAppendStringInfoString(state, " IS UNKNOWN");
+ break;
+ case IS_NOT_UNKNOWN:
+ deparseAppendStringInfoString(state, " IS NOT UNKNOWN");
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "columnDef" and "alter_table_cmd" in gram.y
+static void deparseColumnDef(DeparseState *state, ColumnDef *column_def)
+{
+ ListCell *lc;
+
+ if (column_def->colname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(column_def->colname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->typeName != NULL)
+ {
+ deparseTypeName(state, column_def->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->storage_name)
+ {
+ deparseAppendStringInfoString(state, "STORAGE ");
+ deparseAppendStringInfoString(state, column_def->storage_name);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->raw_default != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseExpr(state, column_def->raw_default, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->compression != NULL)
+ {
+ deparseAppendStringInfoString(state, "COMPRESSION ");
+ deparseAppendStringInfoString(state, column_def->compression);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->fdwoptions != NULL)
+ {
+ deparseCreateGenericOptions(state, column_def->fdwoptions);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ foreach(lc, column_def->constraints)
+ {
+ deparseConstraint(state, castNode(Constraint, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (column_def->collClause != NULL)
+ {
+ deparseCollateClause(state, column_def->collClause);
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "returning_clause" and "returning_option" in gram.y
+static void deparseReturningClause(DeparseState *state, ReturningClause *returning_clause)
+{
+ ListCell *lc;
+
+ deparseAppendPartGroup(state, "RETURNING", DEPARSE_PART_INDENT_AND_MERGE);
+ if (list_length(returning_clause->options) > 0)
+ {
+ deparseAppendStringInfoString(state, "WITH (");
+ foreach(lc, returning_clause->options)
+ {
+ ReturningOption *opt = castNode(ReturningOption, lfirst(lc));
+ switch (opt->option)
+ {
+ case RETURNING_OPTION_OLD:
+ deparseAppendStringInfoString(state, "OLD AS ");
+ break;
+ case RETURNING_OPTION_NEW:
+ deparseAppendStringInfoString(state, "NEW AS ");
+ break;
+ }
+ deparseColId(state, opt->value);
+ if (lnext(returning_clause->options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ deparseTargetList(state, returning_clause->exprs);
+}
+
+static void deparseInsertOverride(DeparseState *state, OverridingKind override)
+{
+ switch (override)
+ {
+ case OVERRIDING_NOT_SET:
+ // Do nothing
+ break;
+ case OVERRIDING_USER_VALUE:
+ deparseAppendStringInfoString(state, "OVERRIDING USER VALUE ");
+ break;
+ case OVERRIDING_SYSTEM_VALUE:
+ deparseAppendStringInfoString(state, "OVERRIDING SYSTEM VALUE ");
+ break;
+ }
+}
+
+static void deparseInsertStmt(DeparseState *state, InsertStmt *insert_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+ DeparseStateNestingLevel *parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (insert_stmt->withClause != NULL)
+ {
+ deparseWithClause(state, insert_stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "INSERT INTO", DEPARSE_PART_INDENT);
+ deparseRangeVar(state, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(insert_stmt->cols) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseInsertColumnList(state, insert_stmt->cols);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseInsertOverride(state, insert_stmt->override);
+
+ if (insert_stmt->selectStmt != NULL)
+ {
+ deparseSelectStmt(state, castNode(SelectStmt, insert_stmt->selectStmt), DEPARSE_NODE_CONTEXT_INSERT_SELECT);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "DEFAULT VALUES ");
+ }
+
+ if (insert_stmt->onConflictClause != NULL)
+ {
+ deparseOnConflictClause(state, insert_stmt->onConflictClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (insert_stmt->returningClause != NULL)
+ deparseReturningClause(state, insert_stmt->returningClause);
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+static void deparseInferClause(DeparseState *state, InferClause *infer_clause)
+{
+ ListCell *lc;
+
+ if (list_length(infer_clause->indexElems) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, infer_clause->indexElems)
+ {
+ deparseIndexElem(state, lfirst(lc));
+ if (lnext(infer_clause->indexElems, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (infer_clause->conname != NULL)
+ {
+ deparseAppendStringInfoString(state, "ON CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(infer_clause->conname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseWhereClause(state, infer_clause->whereClause);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseOnConflictClause(DeparseState *state, OnConflictClause *on_conflict_clause)
+{
+ ListCell *lc;
+
+ deparseAppendPartGroup(state, "ON CONFLICT", DEPARSE_PART_INDENT);
+
+ if (on_conflict_clause->infer != NULL)
+ {
+ deparseInferClause(state, on_conflict_clause->infer);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (on_conflict_clause->action)
+ {
+ case ONCONFLICT_NONE:
+ Assert(false);
+ break;
+ case ONCONFLICT_NOTHING:
+ deparseAppendStringInfoString(state, "DO NOTHING ");
+ break;
+ case ONCONFLICT_UPDATE:
+ deparseAppendStringInfoString(state, "DO UPDATE ");
+ break;
+ }
+
+ if (list_length(on_conflict_clause->targetList) > 0)
+ {
+ deparseAppendPartGroup(state, "SET", DEPARSE_PART_INDENT);
+ deparseSetClauseList(state, on_conflict_clause->targetList);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseWhereClause(state, on_conflict_clause->whereClause);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseUpdateStmt(DeparseState *state, UpdateStmt *update_stmt)
+{
+ ListCell* lc;
+ ListCell* lc2;
+ ListCell* lc3;
+ DeparseStateNestingLevel *parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (update_stmt->withClause != NULL)
+ {
+ deparseWithClause(state, update_stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "UPDATE", DEPARSE_PART_INDENT);
+ deparseRangeVar(state, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(update_stmt->targetList) > 0)
+ {
+ deparseAppendPartGroup(state, "SET", DEPARSE_PART_INDENT);
+ deparseSetClauseList(state, update_stmt->targetList);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseFromClause(state, update_stmt->fromClause);
+ deparseWhereOrCurrentClause(state, update_stmt->whereClause);
+
+ if (update_stmt->returningClause != NULL)
+ deparseReturningClause(state, update_stmt->returningClause);
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+// "MergeStmt" in gram.y
+static void deparseMergeStmt(DeparseState *state, MergeStmt *merge_stmt)
+{
+ DeparseStateNestingLevel *parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (merge_stmt->withClause != NULL)
+ {
+ deparseWithClause(state, merge_stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "MERGE", DEPARSE_PART_INDENT);
+ deparseAppendStringInfoString(state, "INTO ");
+ deparseRangeVar(state, merge_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendPartGroup(state, "USING", DEPARSE_PART_INDENT);
+ deparseTableRef(state, merge_stmt->sourceRelation);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "ON ");
+ deparseExpr(state, merge_stmt->joinCondition, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+
+ ListCell *lc;
+ foreach (lc, merge_stmt->mergeWhenClauses)
+ {
+ MergeWhenClause *clause = castNode(MergeWhenClause, lfirst(lc));
+
+ deparseAppendStringInfoString(state, "WHEN ");
+
+ switch (clause->matchKind)
+ {
+ case MERGE_WHEN_MATCHED:
+ deparseAppendStringInfoString(state, "MATCHED ");
+ break;
+ case MERGE_WHEN_NOT_MATCHED_BY_SOURCE:
+ deparseAppendStringInfoString(state, "NOT MATCHED BY SOURCE ");
+ break;
+ case MERGE_WHEN_NOT_MATCHED_BY_TARGET:
+ deparseAppendStringInfoString(state, "NOT MATCHED ");
+ break;
+ }
+
+ if (clause->condition)
+ {
+ deparseAppendStringInfoString(state, "AND ");
+ deparseExpr(state, clause->condition, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "THEN ");
+
+ switch (clause->commandType) {
+ case CMD_INSERT:
+ deparseAppendStringInfoString(state, "INSERT ");
+
+ if (clause->targetList) {
+ deparseAppendStringInfoChar(state, '(');
+ deparseInsertColumnList(state, clause->targetList);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseInsertOverride(state, clause->override);
+
+ if (clause->values) {
+ deparseAppendStringInfoString(state, "VALUES (");
+ deparseExprList(state, clause->values);
+ deparseAppendStringInfoString(state, ")");
+ } else {
+ deparseAppendStringInfoString(state, "DEFAULT VALUES ");
+ }
+
+ break;
+ case CMD_UPDATE:
+ deparseAppendStringInfoString(state, "UPDATE SET ");
+ deparseSetClauseList(state, clause->targetList);
+ break;
+ case CMD_DELETE:
+ deparseAppendStringInfoString(state, "DELETE");
+ break;
+ case CMD_NOTHING:
+ deparseAppendStringInfoString(state, "DO NOTHING");
+ break;
+ default:
+ elog(ERROR, "deparse: unpermitted command type in merge statement: %d", clause->commandType);
+ break;
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (merge_stmt->returningClause != NULL)
+ deparseReturningClause(state, merge_stmt->returningClause);
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+static void deparseDeleteStmt(DeparseState *state, DeleteStmt *delete_stmt)
+{
+ DeparseStateNestingLevel *parent_level = deparseStateIncreaseNestingLevel(state);
+
+ if (delete_stmt->withClause != NULL)
+ {
+ deparseWithClause(state, delete_stmt->withClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "DELETE", DEPARSE_PART_INDENT);
+ deparseAppendStringInfoString(state, "FROM ");
+ deparseRangeVar(state, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (delete_stmt->usingClause != NULL)
+ {
+ deparseAppendPartGroup(state, "USING", DEPARSE_PART_INDENT);
+ deparseFromList(state, delete_stmt->usingClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseWhereOrCurrentClause(state, delete_stmt->whereClause);
+
+ if (delete_stmt->returningClause != NULL)
+ deparseReturningClause(state, delete_stmt->returningClause);
+
+ removeTrailingSpace(state);
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+static void deparseLockingClause(DeparseState *state, LockingClause *locking_clause)
+{
+ ListCell *lc;
+
+ switch (locking_clause->strength)
+ {
+ case LCS_NONE:
+ /* no such clause - only used in PlanRowMark */
+ Assert(false);
+ break;
+ case LCS_FORKEYSHARE:
+ deparseAppendPartGroup(state, "FOR KEY SHARE", DEPARSE_PART_INDENT);
+ break;
+ case LCS_FORSHARE:
+ deparseAppendPartGroup(state, "FOR SHARE", DEPARSE_PART_INDENT);
+ break;
+ case LCS_FORNOKEYUPDATE:
+ deparseAppendPartGroup(state, "FOR NO KEY UPDATE", DEPARSE_PART_INDENT);
+ break;
+ case LCS_FORUPDATE:
+ deparseAppendPartGroup(state, "FOR UPDATE", DEPARSE_PART_INDENT);
+ break;
+ }
+
+ if (list_length(locking_clause->lockedRels) > 0)
+ {
+ deparseAppendStringInfoString(state, "OF ");
+ deparseQualifiedNameList(state, locking_clause->lockedRels);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (locking_clause->waitPolicy)
+ {
+ case LockWaitError:
+ deparseAppendStringInfoString(state, "NOWAIT");
+ break;
+ case LockWaitSkip:
+ deparseAppendStringInfoString(state, "SKIP LOCKED");
+ break;
+ case LockWaitBlock:
+ // Default
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseSetToDefault(DeparseState *state, SetToDefault *set_to_default)
+{
+ deparseAppendStringInfoString(state, "DEFAULT");
+}
+
+static void deparseCreateCastStmt(DeparseState *state, CreateCastStmt *create_cast_stmt)
+{
+ ListCell *lc;
+ ListCell *lc2;
+
+ deparseAppendStringInfoString(state, "CREATE CAST (");
+ deparseTypeName(state, create_cast_stmt->sourcetype);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, create_cast_stmt->targettype);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (create_cast_stmt->func != NULL)
+ {
+ deparseAppendStringInfoString(state, "WITH FUNCTION ");
+ deparseFunctionWithArgtypes(state, create_cast_stmt->func);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (create_cast_stmt->inout)
+ {
+ deparseAppendStringInfoString(state, "WITH INOUT ");
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "WITHOUT FUNCTION ");
+ }
+
+ switch (create_cast_stmt->context)
+ {
+ case COERCION_IMPLICIT:
+ deparseAppendStringInfoString(state, "AS IMPLICIT");
+ break;
+ case COERCION_ASSIGNMENT:
+ deparseAppendStringInfoString(state, "AS ASSIGNMENT");
+ break;
+ case COERCION_PLPGSQL:
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case COERCION_EXPLICIT:
+ // Default
+ break;
+ }
+}
+
+static void deparseCreateOpClassStmt(DeparseState *state, CreateOpClassStmt *create_op_class_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE OPERATOR CLASS ");
+
+ deparseAnyName(state, create_op_class_stmt->opclassname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_op_class_stmt->isDefault)
+ deparseAppendStringInfoString(state, "DEFAULT ");
+
+ deparseAppendStringInfoString(state, "FOR TYPE ");
+ deparseTypeName(state, create_op_class_stmt->datatype);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(create_op_class_stmt->amname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_op_class_stmt->opfamilyname != NULL)
+ {
+ deparseAppendStringInfoString(state, "FAMILY ");
+ deparseAnyName(state, create_op_class_stmt->opfamilyname);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "AS ");
+ deparseOpclassItemList(state, create_op_class_stmt->items);
+}
+
+static void deparseCreateOpFamilyStmt(DeparseState *state, CreateOpFamilyStmt *create_op_family_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE OPERATOR FAMILY ");
+
+ deparseAnyName(state, create_op_family_stmt->opfamilyname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(create_op_family_stmt->amname));
+}
+
+static void deparseCreateOpClassItem(DeparseState *state, CreateOpClassItem *create_op_class_item)
+{
+ ListCell *lc = NULL;
+
+ switch (create_op_class_item->itemtype)
+ {
+ case OPCLASS_ITEM_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ deparseAppendStringInfo(state, "%d ", create_op_class_item->number);
+
+ if (create_op_class_item->name != NULL)
+ {
+ if (create_op_class_item->name->objargs != NULL)
+ deparseOperatorWithArgtypes(state, create_op_class_item->name);
+ else
+ deparseAnyOperator(state, create_op_class_item->name->objname);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_op_class_item->order_family != NULL)
+ {
+ deparseAppendStringInfoString(state, "FOR ORDER BY ");
+ deparseAnyName(state, create_op_class_item->order_family);
+ }
+
+ if (create_op_class_item->class_args != NULL)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeList(state, create_op_class_item->class_args);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ removeTrailingSpace(state);
+ break;
+ case OPCLASS_ITEM_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseAppendStringInfo(state, "%d ", create_op_class_item->number);
+ if (create_op_class_item->class_args != NULL)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeList(state, create_op_class_item->class_args);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ if (create_op_class_item->name != NULL)
+ deparseFunctionWithArgtypes(state, create_op_class_item->name);
+ removeTrailingSpace(state);
+ break;
+ case OPCLASS_ITEM_STORAGETYPE:
+ deparseAppendStringInfoString(state, "STORAGE ");
+ deparseTypeName(state, create_op_class_item->storedtype);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseTableLikeClause(DeparseState *state, TableLikeClause *table_like_clause)
+{
+ deparseAppendStringInfoString(state, "LIKE ");
+ deparseRangeVar(state, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
+ deparseAppendStringInfoString(state, "INCLUDING ALL ");
+ else
+ {
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+ deparseAppendStringInfoString(state, "INCLUDING COMMENTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION)
+ deparseAppendStringInfoString(state, "INCLUDING COMPRESSION ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
+ deparseAppendStringInfoString(state, "INCLUDING CONSTRAINTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
+ deparseAppendStringInfoString(state, "INCLUDING DEFAULTS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
+ deparseAppendStringInfoString(state, "INCLUDING IDENTITY ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED)
+ deparseAppendStringInfoString(state, "INCLUDING GENERATED ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
+ deparseAppendStringInfoString(state, "INCLUDING INDEXES ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
+ deparseAppendStringInfoString(state, "INCLUDING STATISTICS ");
+ if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ deparseAppendStringInfoString(state, "INCLUDING STORAGE ");
+ }
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateDomainStmt(DeparseState *state, CreateDomainStmt *create_domain_stmt)
+{
+ ListCell *lc;
+
+ Assert(create_domain_stmt->typeName != NULL);
+
+ deparseAppendStringInfoString(state, "CREATE DOMAIN ");
+ deparseAnyName(state, create_domain_stmt->domainname);
+ deparseAppendStringInfoString(state, " AS ");
+
+ deparseTypeName(state, create_domain_stmt->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_domain_stmt->collClause != NULL)
+ {
+ deparseCollateClause(state, create_domain_stmt->collClause);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ foreach(lc, create_domain_stmt->constraints)
+ {
+ deparseConstraint(state, castNode(Constraint, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateExtensionStmt(DeparseState *state, CreateExtensionStmt *create_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE EXTENSION ");
+
+ if (create_extension_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseColId(state, create_extension_stmt->extname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ foreach (lc, create_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "schema") == 0)
+ {
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ deparseColId(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ deparseAppendStringInfoString(state, "VERSION ");
+ deparseNonReservedWordOrSconst(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "cascade") == 0)
+ {
+ deparseAppendStringInfoString(state, "CASCADE");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "ColConstraintElem" and "ConstraintElem" in gram.y
+static void deparseConstraint(DeparseState *state, Constraint *constraint, DeparseNodeContext context)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(constraint->conname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ switch (constraint->contype) {
+ case CONSTR_NULL:
+ deparseAppendStringInfoString(state, "NULL ");
+ break;
+ case CONSTR_NOTNULL:
+ deparseAppendStringInfoString(state, "NOT NULL ");
+ break;
+ case CONSTR_DEFAULT:
+ deparseAppendStringInfoString(state, "DEFAULT ");
+ deparseBExpr(state, constraint->raw_expr);
+ break;
+ case CONSTR_IDENTITY:
+ deparseAppendStringInfoString(state, "GENERATED ");
+ switch (constraint->generated_when)
+ {
+ case ATTRIBUTE_IDENTITY_ALWAYS:
+ deparseAppendStringInfoString(state, "ALWAYS ");
+ break;
+ case ATTRIBUTE_IDENTITY_BY_DEFAULT:
+ deparseAppendStringInfoString(state, "BY DEFAULT ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseAppendStringInfoString(state, "AS IDENTITY ");
+ deparseOptParenthesizedSeqOptList(state, constraint->options);
+ break;
+ case CONSTR_GENERATED:
+ Assert(constraint->generated_when == ATTRIBUTE_IDENTITY_ALWAYS);
+ deparseAppendStringInfoString(state, "GENERATED ALWAYS AS (");
+ deparseExpr(state, constraint->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ if (constraint->generated_kind == ATTRIBUTE_GENERATED_STORED)
+ deparseAppendStringInfoString(state, "STORED ");
+ else
+ deparseAppendStringInfoString(state, "VIRTUAL ");
+ break;
+ case CONSTR_CHECK:
+ deparseAppendStringInfoString(state, "CHECK (");
+ deparseExpr(state, constraint->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ break;
+ case CONSTR_PRIMARY:
+ deparseAppendStringInfoString(state, "PRIMARY KEY ");
+ break;
+ case CONSTR_UNIQUE:
+ deparseAppendStringInfoString(state, "UNIQUE ");
+ if (constraint->nulls_not_distinct)
+ deparseAppendStringInfoString(state, "NULLS NOT DISTINCT ");
+ break;
+ case CONSTR_EXCLUSION:
+ deparseAppendStringInfoString(state, "EXCLUDE ");
+ if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(constraint->access_method));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, constraint->exclusions)
+ {
+ List *exclusion = castNode(List, lfirst(lc));
+ Assert(list_length(exclusion) == 2);
+ deparseIndexElem(state, castNode(IndexElem, linitial(exclusion)));
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyOperator(state, castNode(List, lsecond(exclusion)));
+ if (lnext(constraint->exclusions, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ if (constraint->where_clause != NULL)
+ {
+ deparseAppendStringInfoString(state, "WHERE (");
+ deparseExpr(state, constraint->where_clause, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ break;
+ case CONSTR_FOREIGN:
+ if (list_length(constraint->fk_attrs) > 0)
+ deparseAppendStringInfoString(state, "FOREIGN KEY ");
+ break;
+ case CONSTR_ATTR_DEFERRABLE:
+ deparseAppendStringInfoString(state, "DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ deparseAppendStringInfoString(state, "NOT DEFERRABLE ");
+ break;
+ case CONSTR_ATTR_DEFERRED:
+ deparseAppendStringInfoString(state, "INITIALLY DEFERRED ");
+ break;
+ case CONSTR_ATTR_IMMEDIATE:
+ deparseAppendStringInfoString(state, "INITIALLY IMMEDIATE ");
+ break;
+ case CONSTR_ATTR_ENFORCED:
+ deparseAppendStringInfoString(state, "ENFORCED ");
+ break;
+ case CONSTR_ATTR_NOT_ENFORCED:
+ deparseAppendStringInfoString(state, "NOT ENFORCED ");
+ break;
+ }
+
+ if (list_length(constraint->keys) > 0)
+ {
+ bool emit_keys = true;
+ bool needs_parens = true;
+
+ if (list_length(constraint->keys) == 1)
+ {
+ Node* key = linitial(constraint->keys);
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_DOMAIN)
+ emit_keys = !(IsA(key, String) && strcmp(castNode(String, key)->sval, "value") == 0);
+ needs_parens = constraint->contype != CONSTR_NULL && constraint->contype != CONSTR_NOTNULL;
+ }
+
+ if (needs_parens)
+ deparseAppendStringInfoChar(state, '(');
+
+ if (emit_keys)
+ deparseColumnList(state, constraint->keys);
+
+ if (constraint->without_overlaps)
+ deparseAppendStringInfoString(state, " WITHOUT OVERLAPS");
+
+ if (needs_parens)
+ deparseAppendStringInfoChar(state, ')');
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(constraint->fk_attrs) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ if (constraint->fk_with_period)
+ deparseColumnListWithPeriod(state, constraint->fk_attrs);
+ else
+ deparseColumnList(state, constraint->fk_attrs);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (constraint->pktable != NULL)
+ {
+ deparseAppendStringInfoString(state, "REFERENCES ");
+ deparseRangeVar(state, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ if (list_length(constraint->pk_attrs) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ if (constraint->pk_with_period)
+ deparseColumnListWithPeriod(state, constraint->pk_attrs);
+ else
+ deparseColumnList(state, constraint->pk_attrs);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ }
+
+ switch (constraint->fk_matchtype)
+ {
+ case FKCONSTR_MATCH_SIMPLE:
+ // Default
+ break;
+ case FKCONSTR_MATCH_FULL:
+ deparseAppendStringInfoString(state, "MATCH FULL ");
+ break;
+ case FKCONSTR_MATCH_PARTIAL:
+ // Not implemented in Postgres
+ Assert(false);
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_upd_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ deparseAppendStringInfoString(state, "ON UPDATE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ deparseAppendStringInfoString(state, "ON UPDATE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ deparseAppendStringInfoString(state, "ON UPDATE SET NULL ");
+ break;
+ case FKCONSTR_ACTION_SETDEFAULT:
+ deparseAppendStringInfoString(state, "ON UPDATE SET DEFAULT ");
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ switch (constraint->fk_del_action)
+ {
+ case FKCONSTR_ACTION_NOACTION:
+ // Default
+ break;
+ case FKCONSTR_ACTION_RESTRICT:
+ deparseAppendStringInfoString(state, "ON DELETE RESTRICT ");
+ break;
+ case FKCONSTR_ACTION_CASCADE:
+ deparseAppendStringInfoString(state, "ON DELETE CASCADE ");
+ break;
+ case FKCONSTR_ACTION_SETNULL:
+ case FKCONSTR_ACTION_SETDEFAULT:
+ deparseAppendStringInfoString(state, "ON DELETE SET ");
+
+ switch (constraint->fk_del_action) {
+ case FKCONSTR_ACTION_SETDEFAULT: deparseAppendStringInfoString(state, "DEFAULT "); break;
+ case FKCONSTR_ACTION_SETNULL: deparseAppendStringInfoString(state, "NULL "); break;
+ }
+
+ if (constraint->fk_del_set_cols) {
+ deparseAppendStringInfoString(state, "(");
+ ListCell *lc;
+ foreach (lc, constraint->fk_del_set_cols) {
+ deparseAppendStringInfoString(state, strVal(lfirst(lc)));
+ if (lfirst(lc) != llast(constraint->fk_del_set_cols))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ")");
+ }
+ break;
+ default:
+ // Not specified
+ break;
+ }
+
+ if (list_length(constraint->including) > 0)
+ {
+ deparseAppendStringInfoString(state, "INCLUDE (");
+ deparseColumnList(state, constraint->including);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ switch (constraint->contype)
+ {
+ case CONSTR_PRIMARY:
+ case CONSTR_UNIQUE:
+ case CONSTR_EXCLUSION:
+ deparseOptWith(state, constraint->options);
+ break;
+ default:
+ break;
+ }
+
+ if (constraint->indexname != NULL)
+ deparseAppendStringInfo(state, "USING INDEX %s ", quote_identifier(constraint->indexname));
+
+ if (constraint->indexspace != NULL)
+ deparseAppendStringInfo(state, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
+
+ if (constraint->deferrable)
+ deparseAppendStringInfoString(state, "DEFERRABLE ");
+
+ if (constraint->initdeferred)
+ deparseAppendStringInfoString(state, "INITIALLY DEFERRED ");
+
+ if (constraint->is_no_inherit)
+ deparseAppendStringInfoString(state, "NO INHERIT ");
+
+ if ((constraint->contype == CONSTR_FOREIGN || constraint->contype == CONSTR_CHECK) && !constraint->is_enforced)
+ deparseAppendStringInfoString(state, "NOT ENFORCED ");
+
+ if (constraint->skip_validation)
+ deparseAppendStringInfoString(state, "NOT VALID ");
+
+ removeTrailingSpace(state);
+}
+
+// "ALTER CONSTRAINT name ConstraintAttributeSpec" in gram.y
+static void deparseATAlterConstraint(DeparseState *state, ATAlterConstraint *constraint)
+{
+ ListCell *lc;
+
+ if (constraint->conname != NULL)
+ {
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(constraint->conname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (constraint->alterEnforceability)
+ {
+ if (constraint->is_enforced)
+ deparseAppendStringInfoString(state, "ENFORCED ");
+ else
+ deparseAppendStringInfoString(state, "NOT ENFORCED ");
+ }
+
+ if (constraint->alterDeferrability)
+ {
+ if (constraint->initdeferred)
+ deparseAppendStringInfoString(state, "INITIALLY DEFERRED ");
+ else if (constraint->deferrable)
+ deparseAppendStringInfoString(state, "DEFERRABLE ");
+ else
+ deparseAppendStringInfoString(state, "NOT DEFERRABLE ");
+ }
+
+ if (constraint->alterInheritability)
+ {
+ if (constraint->noinherit)
+ deparseAppendStringInfoString(state, "NO INHERIT ");
+ else
+ deparseAppendStringInfoString(state, "INHERIT ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "ReturnStmt" in gram.y
+static void deparseReturnStmt(DeparseState *state, ReturnStmt *return_stmt)
+{
+ deparseAppendStringInfoString(state, "RETURN ");
+ deparseExpr(state, return_stmt->returnval, DEPARSE_NODE_CONTEXT_A_EXPR);
+}
+
+static void deparseCreateFunctionStmt(DeparseState *state, CreateFunctionStmt *create_function_stmt)
+{
+ ListCell *lc;
+ bool tableFunc = false;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+ if (create_function_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+ if (create_function_stmt->is_procedure)
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ else
+ deparseAppendStringInfoString(state, "FUNCTION ");
+
+ deparseFuncName(state, create_function_stmt->funcname);
+
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode != FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(state, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc) && castNode(FunctionParameter, lfirst(lnext(create_function_stmt->parameters, lc)))->mode != FUNC_PARAM_TABLE)
+ deparseAppendStringInfoString(state, ", ");
+ }
+ else
+ {
+ tableFunc = true;
+ }
+ }
+ deparseAppendStringInfoString(state, ") ");
+
+ if (tableFunc)
+ {
+ deparseAppendStringInfoString(state, "RETURNS TABLE (");
+ foreach(lc, create_function_stmt->parameters)
+ {
+ FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
+ if (function_parameter->mode == FUNC_PARAM_TABLE)
+ {
+ deparseFunctionParameter(state, function_parameter);
+ if (lnext(create_function_stmt->parameters, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ else if (create_function_stmt->returnType != NULL)
+ {
+ deparseAppendStringInfoString(state, "RETURNS ");
+ deparseTypeName(state, create_function_stmt->returnType);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ foreach(lc, create_function_stmt->options)
+ {
+ deparseCreateFuncOptItem(state, castNode(DefElem, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_function_stmt->sql_body)
+ {
+ /* RETURN or BEGIN ... END
+ */
+ if (IsA(create_function_stmt->sql_body, ReturnStmt))
+ {
+ deparseReturnStmt(state, castNode(ReturnStmt, create_function_stmt->sql_body));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "BEGIN ATOMIC ");
+ if (IsA(create_function_stmt->sql_body, List), linitial((List *) create_function_stmt->sql_body) != NULL)
+ {
+ List *body_stmt_list = castNode(List, linitial((List *) create_function_stmt->sql_body));
+ foreach(lc, body_stmt_list)
+ {
+ if (IsA(lfirst(lc), ReturnStmt))
+ {
+ deparseReturnStmt(state, lfirst_node(ReturnStmt, lc));
+ deparseAppendStringInfoString(state, "; ");
+ }
+ else
+ {
+ deparseStmt(state, lfirst(lc));
+ deparseAppendStringInfoString(state, "; ");
+ }
+ }
+ }
+
+ deparseAppendStringInfoString(state, "END ");
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "func_arg", "func_arg_with_default" and other places in gram.y
+static void deparseFunctionParameter(DeparseState *state, FunctionParameter *function_parameter)
+{
+ switch (function_parameter->mode)
+ {
+ case FUNC_PARAM_IN: /* input only */
+ deparseAppendStringInfoString(state, "IN ");
+ break;
+ case FUNC_PARAM_OUT: /* output only */
+ deparseAppendStringInfoString(state, "OUT ");
+ break;
+ case FUNC_PARAM_INOUT: /* both */
+ deparseAppendStringInfoString(state, "INOUT ");
+ break;
+ case FUNC_PARAM_VARIADIC: /* variadic (always input) */
+ deparseAppendStringInfoString(state, "VARIADIC ");
+ break;
+ case FUNC_PARAM_TABLE: /* table function output column */
+ // No special annotation, the caller is expected to correctly put
+ // this into the RETURNS part of the CREATE FUNCTION statement
+ break;
+ case FUNC_PARAM_DEFAULT:
+ // Default
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (function_parameter->name != NULL)
+ {
+ deparseAppendStringInfoString(state, function_parameter->name);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseTypeName(state, function_parameter->argType);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (function_parameter->defexpr != NULL)
+ {
+ deparseAppendStringInfoString(state, "= ");
+ deparseExpr(state, function_parameter->defexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCheckPointStmt(DeparseState *state, CheckPointStmt *check_point_stmt)
+{
+ deparseAppendStringInfoString(state, "CHECKPOINT");
+}
+
+static void deparseCreateSchemaStmt(DeparseState *state, CreateSchemaStmt *create_schema_stmt)
+{
+ ListCell *lc;
+ deparseAppendStringInfoString(state, "CREATE SCHEMA ");
+
+ if (create_schema_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ if (create_schema_stmt->schemaname)
+ {
+ deparseColId(state, create_schema_stmt->schemaname);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_schema_stmt->authrole != NULL)
+ {
+ deparseAppendStringInfoString(state, "AUTHORIZATION ");
+ deparseRoleSpec(state, create_schema_stmt->authrole);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_schema_stmt->schemaElts)
+ {
+ foreach(lc, create_schema_stmt->schemaElts)
+ {
+ deparseSchemaStmt(state, lfirst(lc));
+ if (lnext(create_schema_stmt->schemaElts, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterRoleSetStmt(DeparseState *state, AlterRoleSetStmt *alter_role_set_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER ROLE ");
+
+ if (alter_role_set_stmt->role == NULL)
+ deparseAppendStringInfoString(state, "ALL");
+ else
+ deparseRoleSpec(state, alter_role_set_stmt->role);
+
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_role_set_stmt->database != NULL)
+ {
+ deparseAppendStringInfoString(state, "IN DATABASE ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_role_set_stmt->database));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseVariableSetStmt(state, alter_role_set_stmt->setstmt);
+}
+
+static void deparseCreateConversionStmt(DeparseState *state, CreateConversionStmt *create_conversion_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE ");
+ if (create_conversion_stmt->def)
+ deparseAppendStringInfoString(state, "DEFAULT ");
+
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ deparseAnyName(state, create_conversion_stmt->conversion_name);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseStringLiteral(state, create_conversion_stmt->for_encoding_name);
+ deparseAppendStringInfoString(state, " TO ");
+ deparseStringLiteral(state, create_conversion_stmt->to_encoding_name);
+
+ deparseAppendStringInfoString(state, "FROM ");
+ deparseAnyName(state, create_conversion_stmt->func_name);
+}
+
+static void deparseRoleSpec(DeparseState *state, RoleSpec *role_spec)
+{
+ switch (role_spec->roletype)
+ {
+ case ROLESPEC_CSTRING:
+ Assert(role_spec->rolename != NULL);
+ deparseAppendStringInfoString(state, quote_identifier(role_spec->rolename));
+ break;
+ case ROLESPEC_CURRENT_ROLE:
+ deparseAppendStringInfoString(state, "CURRENT_ROLE");
+ break;
+ case ROLESPEC_CURRENT_USER:
+ deparseAppendStringInfoString(state, "CURRENT_USER");
+ break;
+ case ROLESPEC_SESSION_USER:
+ deparseAppendStringInfoString(state, "SESSION_USER");
+ break;
+ case ROLESPEC_PUBLIC:
+ deparseAppendStringInfoString(state, "public");
+ break;
+ }
+}
+
+// "part_elem" in gram.y
+static void deparsePartitionElem(DeparseState *state, PartitionElem *partition_elem)
+{
+ ListCell *lc;
+
+ if (partition_elem->name != NULL)
+ {
+ deparseColId(state, partition_elem->name);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (partition_elem->expr != NULL)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, partition_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseOptCollate(state, partition_elem->collation);
+ deparseAnyName(state, partition_elem->opclass);
+
+ removeTrailingSpace(state);
+}
+
+static void deparsePartitionSpec(DeparseState *state, PartitionSpec *partition_spec)
+{
+ ListCell *lc;
+
+ deparseAppendPartGroup(state, "PARTITION BY", DEPARSE_PART_INDENT);
+
+ switch (partition_spec->strategy)
+ {
+ case PARTITION_STRATEGY_LIST:
+ deparseAppendStringInfoString(state, "LIST");
+ break;
+ case PARTITION_STRATEGY_HASH:
+ deparseAppendStringInfoString(state, "HASH");
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ deparseAppendStringInfoString(state, "RANGE");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, " (");
+ foreach(lc, partition_spec->partParams)
+ {
+ deparsePartitionElem(state, castNode(PartitionElem, lfirst(lc)));
+ if (lnext(partition_spec->partParams, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparsePartitionBoundSpec(DeparseState *state, PartitionBoundSpec *partition_bound_spec)
+{
+ ListCell *lc;
+
+ if (partition_bound_spec->is_default)
+ {
+ deparseAppendStringInfoString(state, "DEFAULT");
+ return;
+ }
+
+ deparseAppendStringInfoString(state, "FOR VALUES ");
+
+ switch (partition_bound_spec->strategy)
+ {
+ case PARTITION_STRATEGY_HASH:
+ deparseAppendStringInfo(state, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
+ break;
+ case PARTITION_STRATEGY_LIST:
+ deparseAppendStringInfoString(state, "IN (");
+ deparseExprList(state, partition_bound_spec->listdatums);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case PARTITION_STRATEGY_RANGE:
+ deparseAppendStringInfoString(state, "FROM (");
+ deparseExprList(state, partition_bound_spec->lowerdatums);
+ deparseAppendStringInfoString(state, ") TO (");
+ deparseExprList(state, partition_bound_spec->upperdatums);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparsePartitionCmd(DeparseState *state, PartitionCmd *partition_cmd)
+{
+ deparseRangeVar(state, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (partition_cmd->bound != NULL)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparsePartitionBoundSpec(state, partition_cmd->bound);
+ }
+ if (partition_cmd->concurrent)
+ deparseAppendStringInfoString(state, " CONCURRENTLY ");
+}
+
+// "TableElement" in gram.y
+static void deparseTableElement(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_ColumnDef:
+ deparseColumnDef(state, castNode(ColumnDef, node));
+ break;
+ case T_TableLikeClause:
+ deparseTableLikeClause(state, castNode(TableLikeClause, node));
+ break;
+ case T_Constraint:
+ deparseConstraint(state, castNode(Constraint, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+static void deparseCreateStmt(DeparseState *state, CreateStmt *create_stmt, bool is_foreign_table)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (is_foreign_table)
+ deparseAppendStringInfoString(state, "FOREIGN ");
+
+ deparseOptTemp(state, create_stmt->relation->relpersistence);
+
+ deparseAppendStringInfoString(state, "TABLE ");
+
+ if (create_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseRangeVar(state, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_stmt->ofTypename != NULL)
+ {
+ deparseAppendStringInfoString(state, "OF ");
+ deparseTypeName(state, create_stmt->ofTypename);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ Assert(list_length(create_stmt->inhRelations) == 1);
+ deparseAppendStringInfoString(state, "PARTITION OF ");
+ deparseRangeVar(state, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(create_stmt->tableElts) > 0)
+ {
+ DeparseStateNestingLevel *parent_level = NULL;
+ // In raw parse output tableElts contains both columns and constraints
+ // (and the constraints field is NIL)
+ deparseAppendStringInfoChar(state, '(');
+ parent_level = deparseStateIncreaseNestingLevel(state);
+ foreach(lc, create_stmt->tableElts)
+ {
+ deparseTableElement(state, lfirst(lc));
+ if (lnext(create_stmt->tableElts, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ deparseAppendStringInfoString(state, ") ");
+ }
+ else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
+ {
+ deparseAppendStringInfoString(state, "() ");
+ }
+
+ if (create_stmt->partbound != NULL)
+ {
+ deparsePartitionBoundSpec(state, create_stmt->partbound);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ deparseOptInherit(state, create_stmt->inhRelations);
+ }
+
+ if (create_stmt->partspec != NULL)
+ {
+ deparsePartitionSpec(state, create_stmt->partspec);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_stmt->accessMethod != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(create_stmt->accessMethod));
+ }
+
+ deparseOptWith(state, create_stmt->options);
+
+ switch (create_stmt->oncommit)
+ {
+ case ONCOMMIT_NOOP:
+ // No ON COMMIT clause
+ break;
+ case ONCOMMIT_PRESERVE_ROWS:
+ deparseAppendStringInfoString(state, "ON COMMIT PRESERVE ROWS ");
+ break;
+ case ONCOMMIT_DELETE_ROWS:
+ deparseAppendStringInfoString(state, "ON COMMIT DELETE ROWS ");
+ break;
+ case ONCOMMIT_DROP:
+ deparseAppendStringInfoString(state, "ON COMMIT DROP ");
+ break;
+ }
+
+ if (create_stmt->tablespacename != NULL)
+ {
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseAppendStringInfoString(state, quote_identifier(create_stmt->tablespacename));
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateFdwStmt(DeparseState *state, CreateFdwStmt *create_fdw_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE FOREIGN DATA WRAPPER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_fdw_stmt->fdwname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(create_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(state, create_fdw_stmt->func_options);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseCreateGenericOptions(state, create_fdw_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterFdwStmt(DeparseState *state, AlterFdwStmt *alter_fdw_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER FOREIGN DATA WRAPPER ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_fdw_stmt->fdwname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(alter_fdw_stmt->func_options) > 0)
+ {
+ deparseFdwOptions(state, alter_fdw_stmt->func_options);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(alter_fdw_stmt->options) > 0)
+ deparseAlterGenericOptions(state, alter_fdw_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateForeignServerStmt(DeparseState *state, CreateForeignServerStmt *create_foreign_server_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE SERVER ");
+ if (create_foreign_server_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+ deparseAppendStringInfoString(state, quote_identifier(create_foreign_server_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_foreign_server_stmt->servertype != NULL)
+ {
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseStringLiteral(state, create_foreign_server_stmt->servertype);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_foreign_server_stmt->version != NULL)
+ {
+ deparseAppendStringInfoString(state, "VERSION ");
+ deparseStringLiteral(state, create_foreign_server_stmt->version);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_foreign_server_stmt->fdwname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseCreateGenericOptions(state, create_foreign_server_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterForeignServerStmt(DeparseState *state, AlterForeignServerStmt *alter_foreign_server_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER SERVER ");
+
+ deparseAppendStringInfoString(state, quote_identifier(alter_foreign_server_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_foreign_server_stmt->has_version)
+ {
+ deparseAppendStringInfoString(state, "VERSION ");
+ if (alter_foreign_server_stmt->version != NULL)
+ deparseStringLiteral(state, alter_foreign_server_stmt->version);
+ else
+ deparseAppendStringInfoString(state, "NULL");
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (list_length(alter_foreign_server_stmt->options) > 0)
+ deparseAlterGenericOptions(state, alter_foreign_server_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateUserMappingStmt(DeparseState *state, CreateUserMappingStmt *create_user_mapping_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE USER MAPPING ");
+ if (create_user_mapping_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseRoleSpec(state, create_user_mapping_stmt->user);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_user_mapping_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseCreateGenericOptions(state, create_user_mapping_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreatedbStmt(DeparseState *state, CreatedbStmt *createdb_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE DATABASE ");
+ deparseColId(state, createdb_stmt->dbname);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseCreatedbOptList(state, createdb_stmt->options);
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterUserMappingStmt(DeparseState *state, AlterUserMappingStmt *alter_user_mapping_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER USER MAPPING FOR ");
+ deparseRoleSpec(state, alter_user_mapping_stmt->user);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_user_mapping_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAlterGenericOptions(state, alter_user_mapping_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDropUserMappingStmt(DeparseState *state, DropUserMappingStmt *drop_user_mapping_stmt)
+{
+ deparseAppendStringInfoString(state, "DROP USER MAPPING ");
+
+ if (drop_user_mapping_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseRoleSpec(state, drop_user_mapping_stmt->user);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(drop_user_mapping_stmt->servername));
+}
+
+static void deparseSecLabelStmt(DeparseState *state, SecLabelStmt *sec_label_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "SECURITY LABEL ");
+
+ if (sec_label_stmt->provider != NULL)
+ {
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseAppendStringInfoString(state, quote_identifier(sec_label_stmt->provider));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "ON ");
+
+ switch (sec_label_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ deparseAppendStringInfoString(state, "COLUMN ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ deparseAnyName(state, castNode(List, sec_label_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_ROLE:
+ deparseAppendStringInfoString(state, "ROLE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseAppendStringInfoString(state, "SUBSCRIPTION ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(sec_label_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseTypeName(state, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ deparseTypeName(state, castNode(TypeName, sec_label_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECT ");
+ deparseValue(state, (union ValUnion *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, sec_label_stmt->object));
+ break;
+ default:
+ // Not supported in the parser
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, " IS ");
+
+ if (sec_label_stmt->label != NULL)
+ deparseStringLiteral(state, sec_label_stmt->label);
+ else
+ deparseAppendStringInfoString(state, "NULL");
+}
+
+static void deparseCreateForeignTableStmt(DeparseState *state, CreateForeignTableStmt *create_foreign_table_stmt)
+{
+ ListCell *lc;
+
+ deparseCreateStmt(state, &create_foreign_table_stmt->base, true);
+
+ deparseAppendStringInfoString(state, " SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_foreign_table_stmt->servername));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(create_foreign_table_stmt->options) > 0)
+ deparseAlterGenericOptions(state, create_foreign_table_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseImportForeignSchemaStmt(DeparseState *state, ImportForeignSchemaStmt *import_foreign_schema_stmt)
+{
+ deparseAppendStringInfoString(state, "IMPORT FOREIGN SCHEMA ");
+
+ deparseAppendStringInfoString(state, import_foreign_schema_stmt->remote_schema);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (import_foreign_schema_stmt->list_type)
+ {
+ case FDW_IMPORT_SCHEMA_ALL:
+ // Default
+ break;
+ case FDW_IMPORT_SCHEMA_LIMIT_TO:
+ deparseAppendStringInfoString(state, "LIMIT TO (");
+ deparseRelationExprList(state, import_foreign_schema_stmt->table_list);
+ deparseAppendStringInfoString(state, ") ");
+ break;
+ case FDW_IMPORT_SCHEMA_EXCEPT:
+ deparseAppendStringInfoString(state, "EXCEPT (");
+ deparseRelationExprList(state, import_foreign_schema_stmt->table_list);
+ deparseAppendStringInfoString(state, ") ");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "FROM SERVER ");
+ deparseAppendStringInfoString(state, quote_identifier(import_foreign_schema_stmt->server_name));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "INTO ");
+ deparseAppendStringInfoString(state, quote_identifier(import_foreign_schema_stmt->local_schema));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseCreateGenericOptions(state, import_foreign_schema_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateTableAsStmt(DeparseState *state, CreateTableAsStmt *create_table_as_stmt)
+{
+ ListCell *lc;
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ deparseOptTemp(state, create_table_as_stmt->into->rel->relpersistence);
+
+ switch (create_table_as_stmt->objtype)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ if (create_table_as_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseIntoClause(state, create_table_as_stmt->into);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "AS ");
+ if (IsA(create_table_as_stmt->query, ExecuteStmt))
+ deparseExecuteStmt(state, castNode(ExecuteStmt, create_table_as_stmt->query));
+ else
+ deparseSelectStmt(state, castNode(SelectStmt, create_table_as_stmt->query), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_table_as_stmt->into->skipData)
+ deparseAppendStringInfoString(state, "WITH NO DATA ");
+
+ removeTrailingSpace(state);
+}
+
+static void deparseViewStmt(DeparseState *state, ViewStmt *view_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (view_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ deparseOptTemp(state, view_stmt->view->relpersistence);
+
+ deparseAppendStringInfoString(state, "VIEW ");
+ deparseRangeVar(state, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(view_stmt->aliases) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, view_stmt->aliases);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseOptWith(state, view_stmt->options);
+
+ deparseAppendStringInfoString(state, "AS ");
+ deparseSelectStmt(state, castNode(SelectStmt, view_stmt->query), DEPARSE_NODE_CONTEXT_NONE);
+
+ switch (view_stmt->withCheckOption)
+ {
+ case NO_CHECK_OPTION:
+ // Default
+ break;
+ case LOCAL_CHECK_OPTION:
+ deparseAppendStringInfoString(state, "WITH LOCAL CHECK OPTION ");
+ break;
+ case CASCADED_CHECK_OPTION:
+ deparseAppendStringInfoString(state, "WITH CHECK OPTION ");
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDropStmt(DeparseState *state, DropStmt *drop_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ deparseAppendStringInfoString(state, "DROP ");
+
+ switch (drop_stmt->removeType)
+ {
+ case OBJECT_ACCESS_METHOD:
+ deparseAppendStringInfoString(state, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ deparseAppendStringInfoString(state, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ deparseAppendStringInfoString(state, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_OPCLASS:
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ break;
+ case OBJECT_OPFAMILY:
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ deparseAppendStringInfoString(state, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ deparseAppendStringInfoString(state, "RULE ");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_TRANSFORM:
+ deparseAppendStringInfoString(state, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, "TRIGGER ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ default:
+ // Other object types are not supported here in the parser
+ Assert(false);
+ }
+
+ if (drop_stmt->concurrent)
+ deparseAppendStringInfoString(state, "CONCURRENTLY ");
+
+ if (drop_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ switch (drop_stmt->removeType)
+ {
+ // drop_type_any_name
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ deparseAnyNameList(state, drop_stmt->objects);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ // drop_type_name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ deparseNameList(state, drop_stmt->objects);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ // drop_type_name_on_any_name
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseColId(state, strVal(llast(l)));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseAnyNameSkipLast(state, l);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_CAST:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ Assert(list_length(l) == 2);
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, castNode(TypeName, lsecond(l)));
+ deparseAppendStringInfoChar(state, ')');
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseColId(state, strVal(linitial(l)));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_TRANSFORM:
+ Assert(list_length(drop_stmt->objects) == 1);
+ l = linitial(drop_stmt->objects);
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " LANGUAGE ");
+ deparseColId(state, strVal(lsecond(l)));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_LANGUAGE:
+ deparseNameList(state, drop_stmt->objects);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseTypeName(state, castNode(TypeName, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_AGGREGATE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_OPERATOR:
+ foreach(lc, drop_stmt->objects)
+ {
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, lfirst(lc)));
+ if (lnext(drop_stmt->objects, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseOptDropBehavior(state, drop_stmt->behavior);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseGroupingSet(DeparseState *state, GroupingSet *grouping_set)
+{
+ switch(grouping_set->kind)
+ {
+ case GROUPING_SET_EMPTY:
+ deparseAppendStringInfoString(state, "()");
+ break;
+ case GROUPING_SET_SIMPLE:
+ // Not present in raw parse trees
+ Assert(false);
+ break;
+ case GROUPING_SET_ROLLUP:
+ deparseAppendStringInfoString(state, "ROLLUP (");
+ deparseExprList(state, grouping_set->content);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case GROUPING_SET_CUBE:
+ deparseAppendStringInfoString(state, "CUBE (");
+ deparseExprList(state, grouping_set->content);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case GROUPING_SET_SETS:
+ deparseAppendStringInfoString(state, "GROUPING SETS (");
+ deparseGroupByList(state, grouping_set->content);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ }
+}
+
+static void deparseDropTableSpaceStmt(DeparseState *state, DropTableSpaceStmt *drop_table_space_stmt)
+{
+ deparseAppendStringInfoString(state, "DROP TABLESPACE ");
+
+ if (drop_table_space_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAppendStringInfoString(state, drop_table_space_stmt->tablespacename);
+}
+
+static void deparseAlterObjectDependsStmt(DeparseState *state, AlterObjectDependsStmt *alter_object_depends_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (alter_object_depends_stmt->objectType)
+ {
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
+ break;
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, "TRIGGER ");
+ deparseColId(state, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ deparseRangeVar(state, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ deparseRangeVar(state, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ default:
+ // No other object types supported here
+ Assert(false);
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_object_depends_stmt->remove)
+ deparseAppendStringInfoString(state, "NO ");
+
+ deparseAppendStringInfo(state, "DEPENDS ON EXTENSION %s", alter_object_depends_stmt->extname->sval);
+}
+
+static void deparseAlterObjectSchemaStmt(DeparseState *state, AlterObjectSchemaStmt *alter_object_schema_stmt)
+{
+ List *l = NULL;
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (alter_object_schema_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_EXTENSION:
+ deparseAppendStringInfoString(state, "EXTENSION ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(alter_object_schema_stmt->object)));
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_object_schema_stmt->object);
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_object_schema_stmt->object);
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ if (alter_object_schema_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseRangeVar(state, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseAnyName(state, castNode(List, alter_object_schema_stmt->object));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, " SET SCHEMA ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_object_schema_stmt->newschema));
+}
+
+// "alter_table_cmd" in gram.y
+static void deparseAlterTableCmd(DeparseState *state, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
+{
+ ListCell *lc = NULL;
+ const char *options = NULL;
+ bool trailing_missing_ok = false;
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AddColumn: /* add column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ deparseAppendStringInfoString(state, "ADD ATTRIBUTE ");
+ else
+ deparseAppendStringInfoString(state, "ADD COLUMN ");
+ break;
+ case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_ColumnDefault: /* alter column default */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ if (alter_table_cmd->def != NULL)
+ options = "SET DEFAULT";
+ else
+ options = "DROP DEFAULT";
+ break;
+ case AT_CookedColumnDefault: /* add a pre-cooked column default */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropNotNull: /* alter column drop not null */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "DROP NOT NULL";
+ break;
+ case AT_SetNotNull: /* alter column set not null */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET NOT NULL";
+ break;
+ case AT_DropExpression: /* alter column drop expression */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "DROP EXPRESSION";
+ trailing_missing_ok = true;
+ break;
+ case AT_SetStatistics: /* alter column set statistics */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET STATISTICS";
+ break;
+ case AT_SetOptions: /* alter column set ( options ) */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET";
+ break;
+ case AT_ResetOptions: /* alter column reset ( options ) */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "RESET";
+ break;
+ case AT_SetStorage: /* alter column set storage */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET STORAGE";
+ break;
+ case AT_SetCompression: /* alter column set compression */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "SET COMPRESSION";
+ break;
+ case AT_DropColumn: /* drop column */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ deparseAppendStringInfoString(state, "DROP ATTRIBUTE ");
+ else
+ deparseAppendStringInfoString(state, "DROP ");
+ break;
+ case AT_AddIndex: /* add index */
+ deparseAppendStringInfoString(state, "ADD INDEX ");
+ break;
+ case AT_ReAddIndex: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AddConstraint: /* add constraint */
+ deparseAppendStringInfoString(state, "ADD ");
+ break;
+ case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterConstraint: /* alter constraint */
+ deparseAppendStringInfoString(state, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
+ break;
+ case AT_ValidateConstraint: /* validate constraint */
+ deparseAppendStringInfoString(state, "VALIDATE CONSTRAINT ");
+ break;
+ case AT_AddIndexConstraint: /* add constraint using existing index */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_DropConstraint: /* drop constraint */
+ deparseAppendStringInfoString(state, "DROP CONSTRAINT ");
+ break;
+ case AT_ReAddComment: /* internal to commands/tablecmds.c */
+ case AT_ReAddStatistics: /* internal to commands/tablecmds.c */
+ Assert(false);
+ break;
+ case AT_AlterColumnType: /* alter column type */
+ if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
+ deparseAppendStringInfoString(state, "ALTER ATTRIBUTE ");
+ else
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "TYPE";
+ break;
+ case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ // Handled via special case in def handling
+ break;
+ case AT_ChangeOwner: /* change owner */
+ deparseAppendStringInfoString(state, "OWNER TO ");
+ deparseRoleSpec(state, alter_table_cmd->newowner);
+ break;
+ case AT_ClusterOn: /* CLUSTER ON */
+ deparseAppendStringInfoString(state, "CLUSTER ON ");
+ break;
+ case AT_DropCluster: /* SET WITHOUT CLUSTER */
+ deparseAppendStringInfoString(state, "SET WITHOUT CLUSTER ");
+ break;
+ case AT_SetLogged: /* SET LOGGED */
+ deparseAppendStringInfoString(state, "SET LOGGED ");
+ break;
+ case AT_SetUnLogged: /* SET UNLOGGED */
+ deparseAppendStringInfoString(state, "SET UNLOGGED ");
+ break;
+ case AT_DropOids: /* SET WITHOUT OIDS */
+ deparseAppendStringInfoString(state, "SET WITHOUT OIDS ");
+ break;
+ case AT_SetTableSpace: /* SET TABLESPACE */
+ deparseAppendStringInfoString(state, "SET TABLESPACE ");
+ break;
+ case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
+ deparseAppendStringInfoString(state, "SET ");
+ break;
+ case AT_SetAccessMethod:
+ deparseAppendStringInfo(state, "SET ACCESS METHOD ");
+ break;
+ case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
+ deparseAppendStringInfoString(state, "RESET ");
+ break;
+ case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
+ // Not present in raw parser output
+ Assert(false);
+ break;
+ case AT_EnableTrig: /* ENABLE TRIGGER name */
+ deparseAppendStringInfoString(state, "ENABLE TRIGGER ");
+ break;
+ case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
+ deparseAppendStringInfoString(state, "ENABLE ALWAYS TRIGGER ");
+ break;
+ case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
+ deparseAppendStringInfoString(state, "ENABLE REPLICA TRIGGER ");
+ break;
+ case AT_DisableTrig: /* DISABLE TRIGGER name */
+ deparseAppendStringInfoString(state, "DISABLE TRIGGER ");
+ break;
+ case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
+ deparseAppendStringInfoString(state, "ENABLE TRIGGER ALL ");
+ break;
+ case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
+ deparseAppendStringInfoString(state, "DISABLE TRIGGER ALL ");
+ break;
+ case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
+ deparseAppendStringInfoString(state, "ENABLE TRIGGER USER ");
+ break;
+ case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
+ deparseAppendStringInfoString(state, "DISABLE TRIGGER USER ");
+ break;
+ case AT_EnableRule: /* ENABLE RULE name */
+ deparseAppendStringInfoString(state, "ENABLE RULE ");
+ break;
+ case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
+ deparseAppendStringInfoString(state, "ENABLE ALWAYS RULE ");
+ break;
+ case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
+ deparseAppendStringInfoString(state, "ENABLE REPLICA RULE ");
+ break;
+ case AT_DisableRule: /* DISABLE RULE name */
+ deparseAppendStringInfoString(state, "DISABLE RULE ");
+ break;
+ case AT_AddInherit: /* INHERIT parent */
+ deparseAppendStringInfoString(state, "INHERIT ");
+ break;
+ case AT_DropInherit: /* NO INHERIT parent */
+ deparseAppendStringInfoString(state, "NO INHERIT ");
+ break;
+ case AT_AddOf: /* OF */
+ deparseAppendStringInfoString(state, "OF ");
+ break;
+ case AT_DropOf: /* NOT OF */
+ deparseAppendStringInfoString(state, "NOT OF ");
+ break;
+ case AT_ReplicaIdentity: /* REPLICA IDENTITY */
+ deparseAppendStringInfoString(state, "REPLICA IDENTITY ");
+ break;
+ case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
+ deparseAppendStringInfoString(state, "ENABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
+ deparseAppendStringInfoString(state, "DISABLE ROW LEVEL SECURITY ");
+ break;
+ case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
+ deparseAppendStringInfoString(state, "FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
+ deparseAppendStringInfoString(state, "NO FORCE ROW LEVEL SECURITY ");
+ break;
+ case AT_GenericOptions: /* OPTIONS (...) */
+ // Handled in def field handling
+ break;
+ case AT_AttachPartition: /* ATTACH PARTITION */
+ deparseAppendStringInfoString(state, "ATTACH PARTITION ");
+ break;
+ case AT_DetachPartition: /* DETACH PARTITION */
+ deparseAppendStringInfoString(state, "DETACH PARTITION ");
+ break;
+ case AT_DetachPartitionFinalize: /* DETACH PARTITION FINALIZE */
+ deparseAppendStringInfoString(state, "DETACH PARTITION ");
+ break;
+ case AT_AddIdentity: /* ADD IDENTITY */
+ deparseAppendStringInfoString(state, "ALTER ");
+ options = "ADD";
+ // Other details are output via the constraint node (in def field)
+ break;
+ case AT_SetIdentity: /* SET identity column options */
+ deparseAppendStringInfoString(state, "ALTER ");
+ break;
+ case AT_DropIdentity: /* DROP IDENTITY */
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ options = "DROP IDENTITY";
+ trailing_missing_ok = true;
+ break;
+ case AT_SetExpression:
+ deparseAppendStringInfoString(state, "ALTER COLUMN ");
+ break;
+ }
+
+ if (alter_table_cmd->missing_ok && !trailing_missing_ok)
+ {
+ if (alter_table_cmd->subtype == AT_AddColumn)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+ else
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ }
+
+ if (alter_table_cmd->name != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(alter_table_cmd->name));
+ deparseAppendStringInfoChar(state, ' ');
+ } else if (alter_table_cmd->subtype == AT_SetAccessMethod)
+ {
+ deparseAppendStringInfoString(state, " DEFAULT");
+ }
+
+ if (alter_table_cmd->num > 0)
+ deparseAppendStringInfo(state, "%d ", alter_table_cmd->num);
+
+ if (options != NULL)
+ {
+ deparseAppendStringInfoString(state, options);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (alter_table_cmd->missing_ok && trailing_missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ switch (alter_table_cmd->subtype)
+ {
+ case AT_AttachPartition:
+ case AT_DetachPartition:
+ deparsePartitionCmd(state, castNode(PartitionCmd, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_DetachPartitionFinalize:
+ deparsePartitionCmd(state, castNode(PartitionCmd, alter_table_cmd->def));
+ deparseAppendStringInfoString(state, " FINALIZE ");
+ break;
+ case AT_AddColumn:
+ case AT_AlterColumnType:
+ deparseColumnDef(state, castNode(ColumnDef, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_ColumnDefault:
+ if (alter_table_cmd->def != NULL)
+ {
+ deparseExpr(state, alter_table_cmd->def, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ break;
+ case AT_SetStatistics:
+ if (alter_table_cmd->def != NULL)
+ deparseSignedIconst(state, alter_table_cmd->def);
+ else
+ deparseAppendStringInfoString(state, "DEFAULT");
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetOptions:
+ case AT_ResetOptions:
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+ deparseRelOptions(state, castNode(List, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetStorage:
+ deparseColId(state, strVal(alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetCompression:
+ if (strcmp(strVal(alter_table_cmd->def), "default") == 0)
+ deparseAppendStringInfoString(state, "DEFAULT");
+ else
+ deparseColId(state, strVal(alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AddIdentity:
+ case AT_AddConstraint:
+ deparseConstraint(state, castNode(Constraint, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AlterConstraint:
+ deparseATAlterConstraint(state, castNode(ATAlterConstraint, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetIdentity:
+ deparseAlterIdentityColumnOptionList(state, castNode(List, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AlterColumnGenericOptions:
+ case AT_GenericOptions:
+ deparseAlterGenericOptions(state, castNode(List, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AddInherit:
+ case AT_DropInherit:
+ deparseRangeVar(state, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_AddOf:
+ deparseTypeName(state, castNode(TypeName, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_ReplicaIdentity:
+ deparseReplicaIdentityStmt(state, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case AT_SetExpression:
+ deparseAppendStringInfoString(state, "SET EXPRESSION AS (");
+ deparseExpr(state, alter_table_cmd->def, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ default:
+ Assert(alter_table_cmd->def == NULL);
+ break;
+ }
+
+ deparseOptDropBehavior(state, alter_table_cmd->behavior);
+
+ removeTrailingSpace(state);
+}
+
+static DeparseNodeContext deparseAlterTableObjType(DeparseState *state, ObjectType type)
+{
+ switch (type)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ return DEPARSE_NODE_CONTEXT_ALTER_TYPE;
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ return DEPARSE_NODE_CONTEXT_NONE;
+}
+
+static void deparseAlterTableMoveAllStmt(DeparseState *state, AlterTableMoveAllStmt *move_all_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER ");
+ deparseAlterTableObjType(state, move_all_stmt->objtype);
+
+ deparseAppendStringInfoString(state, "ALL IN TABLESPACE ");
+ deparseAppendStringInfoString(state, move_all_stmt->orig_tablespacename);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (move_all_stmt->roles)
+ {
+ deparseAppendStringInfoString(state, "OWNED BY ");
+ deparseRoleList(state, move_all_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "SET TABLESPACE ");
+ deparseAppendStringInfoString(state, move_all_stmt->new_tablespacename);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (move_all_stmt->nowait)
+ {
+ deparseAppendStringInfoString(state, "NOWAIT");
+ }
+}
+
+static void deparseAlterTableStmt(DeparseState *state, AlterTableStmt *alter_table_stmt)
+{
+ ListCell *lc;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+ DeparseNodeContext context = deparseAlterTableObjType(state, alter_table_stmt->objtype);
+
+ if (alter_table_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseRangeVar(state, alter_table_stmt->relation, context);
+ deparseAppendStringInfoChar(state, ' ');
+
+ parent_level = deparseStateIncreaseNestingLevel(state);
+ foreach(lc, alter_table_stmt->cmds)
+ {
+ deparseAlterTableCmd(state, castNode(AlterTableCmd, lfirst(lc)), context);
+ if (lnext(alter_table_stmt->cmds, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+
+static void deparseAlterTableSpaceOptionsStmt(DeparseState *state, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER TABLESPACE ");
+ deparseColId(state, alter_table_space_options_stmt->tablespacename);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_table_space_options_stmt->isReset)
+ deparseAppendStringInfoString(state, "RESET ");
+ else
+ deparseAppendStringInfoString(state, "SET ");
+
+ deparseRelOptions(state, alter_table_space_options_stmt->options);
+}
+
+// "AlterDomainStmt" in gram.y
+static void deparseAlterDomainStmt(DeparseState *state, AlterDomainStmt *alter_domain_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER DOMAIN ");
+ deparseAnyName(state, alter_domain_stmt->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (alter_domain_stmt->subtype)
+ {
+ case 'T':
+ if (alter_domain_stmt->def != NULL)
+ {
+ deparseAppendStringInfoString(state, "SET DEFAULT ");
+ deparseExpr(state, alter_domain_stmt->def, DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "DROP DEFAULT");
+ }
+ break;
+ case 'N':
+ deparseAppendStringInfoString(state, "DROP NOT NULL");
+ break;
+ case 'O':
+ deparseAppendStringInfoString(state, "SET NOT NULL");
+ break;
+ case 'C':
+ deparseAppendStringInfoString(state, "ADD ");
+ deparseConstraint(state, castNode(Constraint, alter_domain_stmt->def), DEPARSE_NODE_CONTEXT_ALTER_DOMAIN);
+ break;
+ case 'X':
+ deparseAppendStringInfoString(state, "DROP CONSTRAINT ");
+ if (alter_domain_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_domain_stmt->name));
+ if (alter_domain_stmt->behavior == DROP_CASCADE)
+ deparseAppendStringInfoString(state, " CASCADE");
+ break;
+ case 'V':
+ deparseAppendStringInfoString(state, "VALIDATE CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_domain_stmt->name));
+ break;
+ default:
+ // No other subtypes supported by the parser
+ Assert(false);
+ }
+}
+
+static void deparseRenameStmt(DeparseState *state, RenameStmt *rename_stmt)
+{
+ List *l = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_DOMCONSTRAINT:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_ROLE:
+ deparseAppendStringInfoString(state, "ROLE ");
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ break;
+ case OBJECT_OPCLASS:
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_POLICY:
+ deparseAppendStringInfoString(state, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseAppendStringInfoString(state, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_TABCONSTRAINT:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_COLUMN:
+ switch (rename_stmt->relationType)
+ {
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ default:
+ Assert(false);
+ }
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_RULE:
+ deparseAppendStringInfoString(state, "RULE ");
+ break;
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, "TRIGGER ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_ATTRIBUTE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (rename_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ switch (rename_stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAnyName(state, castNode(List, rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, rename_stmt->object);
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(l))));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_POLICY:
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseColId(state, strVal(rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_COLUMN:
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME COLUMN ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME CONSTRAINT ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, quote_identifier(strVal(rename_stmt->object)));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_DOMAIN:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TYPE:
+ deparseAnyName(state, castNode(List, rename_stmt->object));
+ deparseAppendStringInfoString(state, " RENAME ");
+ break;
+ case OBJECT_ATTRIBUTE:
+ deparseRangeVar(state, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
+ deparseAppendStringInfoString(state, " RENAME ATTRIBUTE ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "TO ");
+ deparseAppendStringInfoString(state, quote_identifier(rename_stmt->newname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseOptDropBehavior(state, rename_stmt->behavior);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseTransactionStmt(DeparseState *state, TransactionStmt *transaction_stmt)
+{
+ ListCell *lc;
+ switch (transaction_stmt->kind)
+ {
+ case TRANS_STMT_BEGIN:
+ deparseAppendStringInfoString(state, "BEGIN ");
+ deparseTransactionModeList(state, transaction_stmt->options);
+ break;
+ case TRANS_STMT_START:
+ deparseAppendStringInfoString(state, "START TRANSACTION ");
+ deparseTransactionModeList(state, transaction_stmt->options);
+ break;
+ case TRANS_STMT_COMMIT:
+ deparseAppendStringInfoString(state, "COMMIT ");
+ if (transaction_stmt->chain)
+ deparseAppendStringInfoString(state, "AND CHAIN ");
+ break;
+ case TRANS_STMT_ROLLBACK:
+ deparseAppendStringInfoString(state, "ROLLBACK ");
+ if (transaction_stmt->chain)
+ deparseAppendStringInfoString(state, "AND CHAIN ");
+ break;
+ case TRANS_STMT_SAVEPOINT:
+ deparseAppendStringInfoString(state, "SAVEPOINT ");
+ deparseAppendStringInfoString(state, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_RELEASE:
+ deparseAppendStringInfoString(state, "RELEASE ");
+ deparseAppendStringInfoString(state, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_ROLLBACK_TO:
+ deparseAppendStringInfoString(state, "ROLLBACK ");
+ deparseAppendStringInfoString(state, "TO SAVEPOINT ");
+ deparseAppendStringInfoString(state, quote_identifier(transaction_stmt->savepoint_name));
+ break;
+ case TRANS_STMT_PREPARE:
+ deparseAppendStringInfoString(state, "PREPARE TRANSACTION ");
+ deparseStringLiteral(state, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_COMMIT_PREPARED:
+ deparseAppendStringInfoString(state, "COMMIT PREPARED ");
+ deparseStringLiteral(state, transaction_stmt->gid);
+ break;
+ case TRANS_STMT_ROLLBACK_PREPARED:
+ deparseAppendStringInfoString(state, "ROLLBACK PREPARED ");
+ deparseStringLiteral(state, transaction_stmt->gid);
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseVariableSetStmt(DeparseState *state, VariableSetStmt* variable_set_stmt)
+{
+ ListCell *lc;
+
+ switch (variable_set_stmt->kind)
+ {
+ case VAR_SET_VALUE: /* SET var = value */
+ deparseAppendStringInfoString(state, "SET ");
+ if (variable_set_stmt->is_local)
+ deparseAppendStringInfoString(state, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "timezone") == 0 && variable_set_stmt->jumble_args)
+ {
+ deparseAppendStringInfoString(state, "TIME ZONE ");
+ deparseVarList(state, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "xmloption") == 0 && variable_set_stmt->jumble_args)
+ {
+ char *option = linitial_node(A_Const, variable_set_stmt->args)->val.sval.sval;
+ deparseAppendStringInfoString(state, "XML OPTION ");
+ if (strcmp(option, "DOCUMENT") == 0)
+ deparseAppendStringInfoString(state, "DOCUMENT ");
+ else if (strcmp(option, "CONTENT") == 0)
+ deparseAppendStringInfoString(state, "CONTENT ");
+ else
+ deparseVarList(state, variable_set_stmt->args);
+ }
+ else
+ {
+ deparseVarName(state, variable_set_stmt->name);
+ deparseAppendStringInfoString(state, " TO ");
+ deparseVarList(state, variable_set_stmt->args);
+ }
+ break;
+ case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
+ deparseAppendStringInfoString(state, "SET ");
+ if (variable_set_stmt->is_local)
+ deparseAppendStringInfoString(state, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "timezone") == 0 && variable_set_stmt->jumble_args)
+ {
+ deparseAppendStringInfoString(state, "TIME ZONE DEFAULT");
+ }
+ else
+ {
+ deparseVarName(state, variable_set_stmt->name);
+ deparseAppendStringInfoString(state, " TO DEFAULT");
+ }
+ break;
+ case VAR_SET_CURRENT: /* SET var FROM CURRENT */
+ deparseAppendStringInfoString(state, "SET ");
+ if (variable_set_stmt->is_local)
+ deparseAppendStringInfoString(state, "LOCAL ");
+ deparseVarName(state, variable_set_stmt->name);
+ deparseAppendStringInfoString(state, " FROM CURRENT");
+ break;
+ case VAR_SET_MULTI: /* special case for SET TRANSACTION ... */
+ Assert(variable_set_stmt->name != NULL);
+ deparseAppendStringInfoString(state, "SET ");
+ if (variable_set_stmt->is_local)
+ deparseAppendStringInfoString(state, "LOCAL ");
+ if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
+ {
+ deparseAppendStringInfoString(state, "TRANSACTION ");
+ deparseTransactionModeList(state, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
+ {
+ deparseAppendStringInfoString(state, "SESSION CHARACTERISTICS AS TRANSACTION ");
+ deparseTransactionModeList(state, variable_set_stmt->args);
+ }
+ else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
+ {
+ deparseAppendStringInfoString(state, "TRANSACTION SNAPSHOT ");
+ deparseStringLiteral(state, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ case VAR_RESET: /* RESET var */
+ deparseAppendStringInfoString(state, "RESET ");
+ deparseVarName(state, variable_set_stmt->name);
+ break;
+ case VAR_RESET_ALL: /* RESET ALL */
+ deparseAppendStringInfoString(state, "RESET ALL");
+ break;
+ }
+}
+
+static void deparseDropdbStmt(DeparseState *state, DropdbStmt *dropdb_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "DROP DATABASE ");
+ if (dropdb_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAppendStringInfoString(state, quote_identifier(dropdb_stmt->dbname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(dropdb_stmt->options) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, dropdb_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "force") == 0)
+ deparseAppendStringInfoString(state, "FORCE");
+ else
+ Assert(false); // Currently there are other supported values
+
+ if (lnext(dropdb_stmt->options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseVacuumStmt(DeparseState *state, VacuumStmt *vacuum_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ if (vacuum_stmt->is_vacuumcmd)
+ deparseAppendStringInfoString(state, "VACUUM ");
+ else
+ deparseAppendStringInfoString(state, "ANALYZE ");
+
+ deparseUtilityOptionList(state, vacuum_stmt->options);
+
+ foreach(lc, vacuum_stmt->rels)
+ {
+ Assert(IsA(lfirst(lc), VacuumRelation));
+ VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
+
+ deparseRangeVar(state, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(rel->va_cols) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc2, rel->va_cols)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lfirst(lc2))));
+ if (lnext(rel->va_cols, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ if (lnext(vacuum_stmt->rels, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseLoadStmt(DeparseState *state, LoadStmt *load_stmt)
+{
+ deparseAppendStringInfoString(state, "LOAD ");
+ deparseStringLiteral(state, load_stmt->filename);
+}
+
+static void deparseLockStmt(DeparseState *state, LockStmt *lock_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "LOCK TABLE ");
+
+ deparseRelationExprList(state, lock_stmt->relations);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (lock_stmt->mode != AccessExclusiveLock)
+ {
+ deparseAppendStringInfoString(state, "IN ");
+ switch (lock_stmt->mode)
+ {
+ case AccessShareLock:
+ deparseAppendStringInfoString(state, "ACCESS SHARE ");
+ break;
+ case RowShareLock:
+ deparseAppendStringInfoString(state, "ROW SHARE ");
+ break;
+ case RowExclusiveLock:
+ deparseAppendStringInfoString(state, "ROW EXCLUSIVE ");
+ break;
+ case ShareUpdateExclusiveLock:
+ deparseAppendStringInfoString(state, "SHARE UPDATE EXCLUSIVE ");
+ break;
+ case ShareLock:
+ deparseAppendStringInfoString(state, "SHARE ");
+ break;
+ case ShareRowExclusiveLock:
+ deparseAppendStringInfoString(state, "SHARE ROW EXCLUSIVE ");
+ break;
+ case ExclusiveLock:
+ deparseAppendStringInfoString(state, "EXCLUSIVE ");
+ break;
+ case AccessExclusiveLock:
+ deparseAppendStringInfoString(state, "ACCESS EXCLUSIVE ");
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+ deparseAppendStringInfoString(state, "MODE ");
+ }
+
+ if (lock_stmt->nowait)
+ deparseAppendStringInfoString(state, "NOWAIT ");
+
+ removeTrailingSpace(state);
+}
+
+static void deparseConstraintsSetStmt(DeparseState *state, ConstraintsSetStmt *constraints_set_stmt)
+{
+ deparseAppendStringInfoString(state, "SET CONSTRAINTS ");
+
+ if (list_length(constraints_set_stmt->constraints) > 0)
+ {
+ deparseQualifiedNameList(state, constraints_set_stmt->constraints);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ALL ");
+ }
+
+ if (constraints_set_stmt->deferred)
+ deparseAppendStringInfoString(state, "DEFERRED");
+ else
+ deparseAppendStringInfoString(state, "IMMEDIATE");
+}
+
+static void deparseExplainStmt(DeparseState *state, ExplainStmt *explain_stmt)
+{
+ ListCell *lc = NULL;
+ char *defname = NULL;
+
+ deparseAppendPartGroup(state, "EXPLAIN", DEPARSE_PART_NO_INDENT);
+
+ deparseUtilityOptionList(state, explain_stmt->options);
+
+ deparseExplainableStmt(state, explain_stmt->query);
+}
+
+static void deparseCopyStmt(DeparseState *state, CopyStmt *copy_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ deparseAppendPartGroup(state, "COPY", DEPARSE_PART_INDENT);
+
+ if (copy_stmt->relation != NULL)
+ {
+ deparseRangeVar(state, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ if (list_length(copy_stmt->attlist) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, copy_stmt->attlist);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (copy_stmt->query != NULL)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparsePreparableStmt(state, copy_stmt->query);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (copy_stmt->is_from)
+ deparseAppendStringInfoString(state, "FROM ");
+ else
+ deparseAppendStringInfoString(state, "TO ");
+
+ if (copy_stmt->is_program)
+ deparseAppendStringInfoString(state, "PROGRAM ");
+
+ if (copy_stmt->filename != NULL)
+ {
+ deparseStringLiteral(state, copy_stmt->filename);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ if (copy_stmt->is_from)
+ deparseAppendStringInfoString(state, "STDIN ");
+ else
+ deparseAppendStringInfoString(state, "STDOUT ");
+ }
+
+ if (list_length(copy_stmt->options) > 0)
+ {
+ // In some cases, equivalent expressions may have slightly different parse trees for `COPY`
+ // statements. For example the following two statements result in different (but equivalent) parse
+ // trees:
+ //
+ // - COPY foo FROM STDIN CSV FREEZE
+ // - COPY foo FROM STDIN WITH (FORMAT CSV, FREEZE)
+ //
+ // In order to make sure we deparse to the "correct" version, we always try to deparse to the older
+ // compact syntax first.
+ //
+ // The old syntax can be seen here in the Postgres 8.4 Reference:
+ // https://www.postgresql.org/docs/8.4/sql-copy.html
+
+ bool old_fmt = true;
+
+ // Loop over the options to see if any require the new `WITH (...)` syntax.
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "freeze") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {}
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {}
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
+ {}
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
+ {}
+ else
+ {
+ old_fmt = false;
+ break;
+ }
+ }
+
+ // Branch to differing output modes, depending on if we can use the old syntax.
+ if (old_fmt) {
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "freeze") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "FREEZE ");
+ }
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "HEADER ");
+ }
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
+ {
+ deparseAppendStringInfoString(state, "CSV ");
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
+ {
+ deparseAppendStringInfoString(state, "FORCE QUOTE ");
+ deparseColumnList(state, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ // This isn't reachable, the conditions here are exactly the same as the first loop above.
+ Assert(false);
+ }
+ }
+ } else {
+ deparseAppendStringInfoString(state, "WITH (");
+ foreach(lc, copy_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+
+ if (strcmp(def_elem->defname, "format") == 0)
+ {
+ deparseAppendStringInfoString(state, "FORMAT ");
+
+ char *format = strVal(def_elem->arg);
+ if (strcmp(format, "binary") == 0)
+ deparseAppendStringInfoString(state, "BINARY");
+ else if (strcmp(format, "csv") == 0)
+ deparseAppendStringInfoString(state, "CSV");
+ else if (strcmp(format, "text") == 0)
+ deparseAppendStringInfoString(state, "TEXT");
+ else
+ Assert(false);
+ }
+ else if (strcmp(def_elem->defname, "freeze") == 0)
+ {
+ deparseAppendStringInfoString(state, "FREEZE");
+ deparseOptBoolean(state, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
+ {
+ deparseAppendStringInfoString(state, "DELIMITER ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "null") == 0)
+ {
+ deparseAppendStringInfoString(state, "NULL ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "header") == 0)
+ {
+ deparseAppendStringInfoString(state, "HEADER");
+ deparseOptBoolean(state, def_elem->arg);
+ }
+ else if (strcmp(def_elem->defname, "quote") == 0)
+ {
+ deparseAppendStringInfoString(state, "QUOTE ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "escape") == 0)
+ {
+ deparseAppendStringInfoString(state, "ESCAPE ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
+ {
+ deparseAppendStringInfoString(state, "FORCE_QUOTE ");
+ if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAppendStringInfoChar(state, '*');
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, castNode(List, def_elem->arg));
+ deparseAppendStringInfoChar(state, ')');
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
+ {
+ deparseAppendStringInfoString(state, "FORCE_NOT_NULL ");
+
+ if (IsA(def_elem->arg, A_Star))
+ deparseAStar(state, castNode(A_Star, def_elem->arg));
+ else
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, castNode(List, def_elem->arg));
+ deparseAppendStringInfoChar(state, ')');
+ }
+ }
+ else if (strcmp(def_elem->defname, "force_null") == 0)
+ {
+ deparseAppendStringInfoString(state, "FORCE_NULL ");
+
+ if (IsA(def_elem->arg, A_Star))
+ deparseAStar(state, castNode(A_Star, def_elem->arg));
+ else
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, castNode(List, def_elem->arg));
+ deparseAppendStringInfoChar(state, ')');
+ }
+ }
+ else if (strcmp(def_elem->defname, "encoding") == 0)
+ {
+ deparseAppendStringInfoString(state, "ENCODING ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ if (def_elem->arg != NULL)
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (def_elem->arg == NULL)
+ {
+ // Nothing
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseOptBooleanOrString(state, strVal(def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
+ {
+ deparseNumericOnly(state, (union ValUnion *) def_elem->arg);
+ }
+ else if (IsA(def_elem->arg, A_Star))
+ {
+ deparseAStar(state, castNode(A_Star, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, List))
+ {
+ List *l = castNode(List, def_elem->arg);
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc2, l)
+ {
+ deparseOptBooleanOrString(state, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+ }
+
+ if (lnext(copy_stmt->options, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+ }
+
+ deparseWhereClause(state, copy_stmt->whereClause);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDoStmt(DeparseState *state, DoStmt *do_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "DO ");
+
+ foreach (lc, do_stmt->args)
+ {
+ DefElem *defel = castNode(DefElem, lfirst(lc));
+ if (strcmp(defel->defname, "language") == 0)
+ {
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(defel->arg)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (strcmp(defel->defname, "as") == 0)
+ {
+ char *strval = strVal(defel->arg);
+ const char *delim = "$$";
+ if (strstr(strval, "$$") != NULL)
+ delim = "$outer$";
+ deparseAppendStringInfoString(state, delim);
+ deparseAppendStringInfoString(state, strval);
+ deparseAppendStringInfoString(state, delim);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDiscardStmt(DeparseState *state, DiscardStmt *discard_stmt)
+{
+ deparseAppendStringInfoString(state, "DISCARD ");
+ switch (discard_stmt->target)
+ {
+ case DISCARD_ALL:
+ deparseAppendStringInfoString(state, "ALL");
+ break;
+ case DISCARD_PLANS:
+ deparseAppendStringInfoString(state, "PLANS");
+ break;
+ case DISCARD_SEQUENCES:
+ deparseAppendStringInfoString(state, "SEQUENCES");
+ break;
+ case DISCARD_TEMP:
+ deparseAppendStringInfoString(state, "TEMP");
+ break;
+ }
+}
+
+static void deparseDefineStmt(DeparseState *state, DefineStmt *define_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (define_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ default:
+ // This shouldn't happen
+ Assert(false);
+ break;
+ }
+
+ if (define_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ switch (define_stmt->kind)
+ {
+ case OBJECT_AGGREGATE:
+ deparseFuncName(state, define_stmt->defnames);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAnyOperator(state, define_stmt->defnames);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_COLLATION:
+ deparseAnyName(state, define_stmt->defnames);
+ break;
+ default:
+ Assert(false);
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
+ {
+ deparseAggrArgs(state, define_stmt->args);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (define_stmt->kind == OBJECT_COLLATION &&
+ list_length(define_stmt->definition) == 1 &&
+ strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
+ {
+ deparseAppendStringInfoString(state, "FROM ");
+ deparseAnyName(state, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
+ }
+ else if (list_length(define_stmt->definition) > 0)
+ {
+ deparseDefinition(state, define_stmt->definition);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCompositeTypeStmt(DeparseState *state, CompositeTypeStmt *composite_type_stmt)
+{
+ ListCell *lc;
+ RangeVar *typevar;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE TYPE ");
+ deparseRangeVar(state, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
+
+ deparseAppendStringInfoString(state, " AS (");
+ parent_level = deparseStateIncreaseNestingLevel(state);
+ foreach(lc, composite_type_stmt->coldeflist)
+ {
+ deparseColumnDef(state, castNode(ColumnDef, lfirst(lc)));
+ if (lnext(composite_type_stmt->coldeflist, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseCreateEnumStmt(DeparseState *state, CreateEnumStmt *create_enum_stmt)
+{
+ ListCell *lc;
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE TYPE ");
+
+ deparseAnyName(state, create_enum_stmt->typeName);
+ deparseAppendStringInfoString(state, " AS ENUM (");
+ parent_level = deparseStateIncreaseNestingLevel(state);
+ foreach(lc, create_enum_stmt->vals)
+ {
+ deparseStringLiteral(state, strVal(lfirst(lc)));
+ if (lnext(create_enum_stmt->vals, lc))
+ deparseAppendCommaAndPart(state);
+ }
+ deparseStateDecreaseNestingLevel(state, parent_level);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseCreateRangeStmt(DeparseState *state, CreateRangeStmt *create_range_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE TYPE ");
+ deparseAnyName(state, create_range_stmt->typeName);
+ deparseAppendStringInfoString(state, " AS RANGE ");
+ deparseDefinition(state, create_range_stmt->params);
+}
+
+static void deparseAlterEnumStmt(DeparseState *state, AlterEnumStmt *alter_enum_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER TYPE ");
+ deparseAnyName(state, alter_enum_stmt->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_enum_stmt->oldVal == NULL)
+ {
+ deparseAppendStringInfoString(state, "ADD VALUE ");
+ if (alter_enum_stmt->skipIfNewValExists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseStringLiteral(state, alter_enum_stmt->newVal);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_enum_stmt->newValNeighbor)
+ {
+ if (alter_enum_stmt->newValIsAfter)
+ deparseAppendStringInfoString(state, "AFTER ");
+ else
+ deparseAppendStringInfoString(state, "BEFORE ");
+ deparseStringLiteral(state, alter_enum_stmt->newValNeighbor);
+ }
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "RENAME VALUE ");
+ deparseStringLiteral(state, alter_enum_stmt->oldVal);
+ deparseAppendStringInfoString(state, " TO ");
+ deparseStringLiteral(state, alter_enum_stmt->newVal);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterExtensionStmt(DeparseState *state, AlterExtensionStmt *alter_extension_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER EXTENSION ");
+ deparseColId(state, alter_extension_stmt->extname);
+ deparseAppendStringInfoString(state, " UPDATE ");
+ foreach (lc, alter_extension_stmt->options)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ if (strcmp(def_elem->defname, "new_version") == 0)
+ {
+ deparseAppendStringInfoString(state, "TO ");
+ deparseNonReservedWordOrSconst(state, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterExtensionContentsStmt(DeparseState *state, AlterExtensionContentsStmt *alter_extension_contents_stmt)
+{
+ List *l = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER EXTENSION ");
+ deparseColId(state, alter_extension_contents_stmt->extname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_extension_contents_stmt->action == 1)
+ deparseAppendStringInfoString(state, "ADD ");
+ else if (alter_extension_contents_stmt->action == -1)
+ deparseAppendStringInfoString(state, "DROP ");
+ else
+ Assert(false);
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ deparseAppendStringInfoString(state, "ACCESS METHOD ");
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_CAST:
+ deparseAppendStringInfoString(state, "CAST ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ break;
+ case OBJECT_OPCLASS:
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ break;
+ case OBJECT_TRANSFORM:
+ deparseAppendStringInfoString(state, "TRANSFORM ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ default:
+ // No other object types are supported here in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (alter_extension_contents_stmt->objtype)
+ {
+ // any_name
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_TABLE:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ deparseAnyName(state, castNode(List, alter_extension_contents_stmt->object));
+ break;
+ // name
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_LANGUAGE:
+ case OBJECT_SCHEMA:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ deparseColId(state, strVal(alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, castNode(TypeName, lsecond(l)));
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ deparseTypeName(state, castNode(TypeName, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ Assert(list_length(l) == 2);
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseColId(state, strVal(linitial(l)));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, alter_extension_contents_stmt->object);
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " LANGUAGE ");
+ deparseColId(state, strVal(lsecond(l)));
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+static void deparseAccessPriv(DeparseState *state, AccessPriv *access_priv)
+{
+ ListCell *lc;
+
+ if (access_priv->priv_name != NULL)
+ {
+ if (strcmp(access_priv->priv_name, "select") == 0)
+ deparseAppendStringInfoString(state, "select");
+ else if (strcmp(access_priv->priv_name, "references") == 0)
+ deparseAppendStringInfoString(state, "references");
+ else if (strcmp(access_priv->priv_name, "create") == 0)
+ deparseAppendStringInfoString(state, "create");
+ else
+ deparseAppendStringInfoString(state, quote_identifier(access_priv->priv_name));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ALL");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(access_priv->cols) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, access_priv->cols);
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseGrantStmt(DeparseState *state, GrantStmt *grant_stmt)
+{
+ ListCell *lc;
+ if (grant_stmt->is_grant)
+ deparseAppendStringInfoString(state, "GRANT ");
+ else
+ deparseAppendStringInfoString(state, "REVOKE ");
+
+ if (!grant_stmt->is_grant && grant_stmt->grant_option)
+ deparseAppendStringInfoString(state, "GRANT OPTION FOR ");
+
+ if (list_length(grant_stmt->privileges) > 0)
+ {
+ foreach(lc, grant_stmt->privileges)
+ {
+ deparseAccessPriv(state, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_stmt->privileges, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ALL ");
+ }
+
+ deparseAppendStringInfoString(state, "ON ");
+
+ deparsePrivilegeTarget(state, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (grant_stmt->is_grant)
+ deparseAppendStringInfoString(state, "TO ");
+ else
+ deparseAppendStringInfoString(state, "FROM ");
+
+ foreach(lc, grant_stmt->grantees)
+ {
+ deparseRoleSpec(state, castNode(RoleSpec, lfirst(lc)));
+ if (lnext(grant_stmt->grantees, lc))
+ deparseAppendStringInfoChar(state, ',');
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (grant_stmt->is_grant && grant_stmt->grant_option)
+ deparseAppendStringInfoString(state, "WITH GRANT OPTION ");
+
+ deparseOptDropBehavior(state, grant_stmt->behavior);
+
+ if (grant_stmt->grantor)
+ {
+ deparseAppendStringInfoString(state, "GRANTED BY ");
+ deparseRoleSpec(state, castNode(RoleSpec, grant_stmt->grantor));
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseGrantRoleStmt(DeparseState *state, GrantRoleStmt *grant_role_stmt)
+{
+ ListCell *lc;
+
+ if (grant_role_stmt->is_grant)
+ deparseAppendStringInfoString(state, "GRANT ");
+ else
+ deparseAppendStringInfoString(state, "REVOKE ");
+
+ if (!grant_role_stmt->is_grant && list_length(grant_role_stmt->opt)) {
+ DefElem *defelem = castNode(DefElem, linitial(grant_role_stmt->opt));
+ Assert(!castNode(Boolean, defelem->arg)->boolval);
+
+ if (strcmp("admin", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "ADMIN ");
+ } else if (strcmp("inherit", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "INHERIT ");
+ } else if (strcmp("set", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "SET ");
+ }
+
+ deparseAppendStringInfoString(state, "OPTION FOR ");
+ }
+
+ foreach(lc, grant_role_stmt->granted_roles)
+ {
+ deparseAccessPriv(state, castNode(AccessPriv, lfirst(lc)));
+ if (lnext(grant_role_stmt->granted_roles, lc))
+ deparseAppendStringInfoChar(state, ',');
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (grant_role_stmt->is_grant)
+ deparseAppendStringInfoString(state, "TO ");
+ else
+ deparseAppendStringInfoString(state, "FROM ");
+
+ deparseRoleList(state, grant_role_stmt->grantee_roles);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (grant_role_stmt->is_grant) {
+ if (list_length(grant_role_stmt->opt) > 0) {
+ deparseAppendStringInfoString(state, "WITH ");
+ }
+
+ foreach(lc, grant_role_stmt->opt) {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp("admin", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "ADMIN ");
+ deparseAppendStringInfoString(state, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ } else if (strcmp("inherit", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "INHERIT ");
+ deparseAppendStringInfoString(state, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ } else if (strcmp("set", defelem->defname) == 0) {
+ deparseAppendStringInfoString(state, "SET ");
+ deparseAppendStringInfoString(state, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
+ }
+
+ if (lnext(grant_role_stmt->opt, lc)) {
+ deparseAppendStringInfoChar(state, ',');
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ if (grant_role_stmt->grantor)
+ {
+ deparseAppendStringInfoString(state, "GRANTED BY ");
+ deparseRoleSpec(state, castNode(RoleSpec, grant_role_stmt->grantor));
+ }
+
+ if (grant_role_stmt->behavior == DROP_CASCADE) {
+ deparseAppendStringInfoString(state, "CASCADE ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDropRoleStmt(DeparseState *state, DropRoleStmt *drop_role_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "DROP ROLE ");
+
+ if (drop_role_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseRoleList(state, drop_role_stmt->roles);
+}
+
+static void deparseIndexStmt(DeparseState *state, IndexStmt *index_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (index_stmt->unique)
+ deparseAppendStringInfoString(state, "UNIQUE ");
+
+ deparseAppendStringInfoString(state, "INDEX ");
+
+ if (index_stmt->concurrent)
+ deparseAppendStringInfoString(state, "CONCURRENTLY ");
+
+ if (index_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ if (index_stmt->idxname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(index_stmt->idxname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendPartGroup(state, "ON", DEPARSE_PART_INDENT);
+ deparseRangeVar(state, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (index_stmt->accessMethod != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(index_stmt->accessMethod));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoChar(state, '(');
+ foreach (lc, index_stmt->indexParams)
+ {
+ deparseIndexElem(state, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexParams, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+
+ if (list_length(index_stmt->indexIncludingParams) > 0)
+ {
+ deparseAppendStringInfoString(state, "INCLUDE (");
+ foreach (lc, index_stmt->indexIncludingParams)
+ {
+ deparseIndexElem(state, castNode(IndexElem, lfirst(lc)));
+ if (lnext(index_stmt->indexIncludingParams, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (index_stmt->nulls_not_distinct)
+ {
+ deparseAppendStringInfoString(state, "NULLS NOT DISTINCT ");
+ }
+
+ deparseOptWith(state, index_stmt->options);
+
+ if (index_stmt->tableSpace != NULL)
+ {
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseAppendStringInfoString(state, quote_identifier(index_stmt->tableSpace));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseWhereClause(state, index_stmt->whereClause);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterOpFamilyStmt(DeparseState *state, AlterOpFamilyStmt *alter_op_family_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER OPERATOR FAMILY ");
+ deparseAnyName(state, alter_op_family_stmt->opfamilyname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_op_family_stmt->amname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_op_family_stmt->isDrop)
+ deparseAppendStringInfoString(state, "DROP ");
+ else
+ deparseAppendStringInfoString(state, "ADD ");
+
+ deparseOpclassItemList(state, alter_op_family_stmt->items);
+}
+
+static void deparsePrepareStmt(DeparseState *state, PrepareStmt *prepare_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "PREPARE ");
+ deparseColId(state, prepare_stmt->name);
+ if (list_length(prepare_stmt->argtypes) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeList(state, prepare_stmt->argtypes);
+ deparseAppendStringInfoChar(state, ')');
+ }
+ deparseAppendStringInfoString(state, " AS ");
+ deparsePreparableStmt(state, prepare_stmt->query);
+}
+
+static void deparseExecuteStmt(DeparseState *state, ExecuteStmt *execute_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "EXECUTE ");
+ deparseAppendStringInfoString(state, quote_identifier(execute_stmt->name));
+ if (list_length(execute_stmt->params) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseExprList(state, execute_stmt->params);
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+static void deparseDeallocateStmt(DeparseState *state, DeallocateStmt *deallocate_stmt)
+{
+ deparseAppendStringInfoString(state, "DEALLOCATE ");
+ if (deallocate_stmt->name != NULL)
+ deparseAppendStringInfoString(state, quote_identifier(deallocate_stmt->name));
+ else
+ deparseAppendStringInfoString(state, "ALL");
+}
+
+// "AlterOptRoleElem" in gram.y
+static void deparseAlterRoleElem(DeparseState *state, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "password") == 0)
+ {
+ deparseAppendStringInfoString(state, "PASSWORD ");
+ if (def_elem->arg == NULL)
+ {
+ deparseAppendStringInfoString(state, "NULL");
+ }
+ else if (IsA(def_elem->arg, ParamRef))
+ {
+ deparseParamRef(state, castNode(ParamRef, def_elem->arg));
+ }
+ else if (IsA(def_elem->arg, String))
+ {
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else
+ {
+ Assert(false);
+ }
+ }
+ else if (strcmp(def_elem->defname, "connectionlimit") == 0)
+ {
+ deparseAppendStringInfo(state, "CONNECTION LIMIT %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "validUntil") == 0)
+ {
+ deparseAppendStringInfoString(state, "VALID UNTIL ");
+ deparseStringLiteral(state, strVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "SUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "superuser") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOSUPERUSER");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "CREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "createrole") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOCREATEROLE");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "REPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOREPLICATION");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "CREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "createdb") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOCREATEDB");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "LOGIN");
+ }
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOLOGIN");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "BYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOBYPASSRLS");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "INHERIT");
+ }
+ else if (strcmp(def_elem->defname, "inherit") == 0 && !boolVal(def_elem->arg))
+ {
+ deparseAppendStringInfoString(state, "NOINHERIT");
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+// "CreateOptRoleElem" in gram.y
+static void deparseCreateRoleElem(DeparseState *state, DefElem *def_elem)
+{
+ if (strcmp(def_elem->defname, "sysid") == 0)
+ {
+ deparseAppendStringInfo(state, "SYSID %d", intVal(def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "adminmembers") == 0)
+ {
+ deparseAppendStringInfoString(state, "ADMIN ");
+ deparseRoleList(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "rolemembers") == 0)
+ {
+ deparseAppendStringInfoString(state, "ROLE ");
+ deparseRoleList(state, castNode(List, def_elem->arg));
+ }
+ else if (strcmp(def_elem->defname, "addroleto") == 0)
+ {
+ deparseAppendStringInfoString(state, "IN ROLE ");
+ deparseRoleList(state, castNode(List, def_elem->arg));
+ }
+ else
+ {
+ deparseAlterRoleElem(state, def_elem);
+ }
+}
+
+static void deparseCreatePLangStmt(DeparseState *state, CreatePLangStmt *create_p_lang_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (create_p_lang_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ if (create_p_lang_stmt->pltrusted)
+ deparseAppendStringInfoString(state, "TRUSTED ");
+
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseNonReservedWordOrSconst(state, create_p_lang_stmt->plname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "HANDLER ");
+ deparseHandlerName(state, create_p_lang_stmt->plhandler);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_p_lang_stmt->plinline)
+ {
+ deparseAppendStringInfoString(state, "INLINE ");
+ deparseHandlerName(state, create_p_lang_stmt->plinline);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_p_lang_stmt->plvalidator)
+ {
+ deparseAppendStringInfoString(state, "VALIDATOR ");
+ deparseHandlerName(state, create_p_lang_stmt->plvalidator);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateRoleStmt(DeparseState *state, CreateRoleStmt *create_role_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ switch (create_role_stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ deparseAppendStringInfoString(state, "ROLE ");
+ break;
+ case ROLESTMT_USER:
+ deparseAppendStringInfoString(state, "USER ");
+ break;
+ case ROLESTMT_GROUP:
+ deparseAppendStringInfoString(state, "GROUP ");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, quote_identifier(create_role_stmt->role));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_role_stmt->options != NULL)
+ {
+ deparseAppendStringInfoString(state, "WITH ");
+ foreach (lc, create_role_stmt->options)
+ {
+ deparseCreateRoleElem(state, castNode(DefElem, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterRoleStmt(DeparseState *state, AlterRoleStmt *alter_role_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
+ {
+ deparseAppendStringInfoString(state, "GROUP ");
+ deparseRoleSpec(state, alter_role_stmt->role);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_role_stmt->action == 1)
+ {
+ deparseAppendStringInfoString(state, "ADD USER ");
+ }
+ else if (alter_role_stmt->action == -1)
+ {
+ deparseAppendStringInfoString(state, "DROP USER ");
+ }
+ else
+ {
+ Assert(false);
+ }
+
+ deparseRoleList(state, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ROLE ");
+ deparseRoleSpec(state, alter_role_stmt->role);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "WITH ");
+ foreach (lc, alter_role_stmt->options)
+ {
+ deparseAlterRoleElem(state, castNode(DefElem, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDeclareCursorStmt(DeparseState *state, DeclareCursorStmt *declare_cursor_stmt)
+{
+ deparseAppendStringInfoString(state, "DECLARE ");
+ deparseAppendStringInfoString(state, quote_identifier(declare_cursor_stmt->portalname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
+ deparseAppendStringInfoString(state, "BINARY ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
+ deparseAppendStringInfoString(state, "SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
+ deparseAppendStringInfoString(state, "NO SCROLL ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
+ deparseAppendStringInfoString(state, "INSENSITIVE ");
+
+ deparseAppendStringInfoString(state, "CURSOR ");
+
+ if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
+ deparseAppendStringInfoString(state, "WITH HOLD ");
+
+ deparseAppendStringInfoString(state, "FOR ");
+
+ deparseSelectStmt(state, castNode(SelectStmt, declare_cursor_stmt->query), DEPARSE_NODE_CONTEXT_NONE);
+}
+
+static void deparseFetchStmt(DeparseState *state, FetchStmt *fetch_stmt)
+{
+ if (fetch_stmt->ismove)
+ deparseAppendStringInfoString(state, "MOVE ");
+ else
+ deparseAppendStringInfoString(state, "FETCH ");
+
+ switch (fetch_stmt->direction)
+ {
+ case FETCH_FORWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ // Default
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ deparseAppendStringInfoString(state, "ALL ");
+ }
+ else
+ {
+ deparseAppendStringInfo(state, "FORWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_BACKWARD:
+ if (fetch_stmt->howMany == 1)
+ {
+ deparseAppendStringInfoString(state, "PRIOR ");
+ }
+ else if (fetch_stmt->howMany == FETCH_ALL)
+ {
+ deparseAppendStringInfoString(state, "BACKWARD ALL ");
+ }
+ else
+ {
+ deparseAppendStringInfo(state, "BACKWARD %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_ABSOLUTE:
+ if (fetch_stmt->howMany == 1)
+ {
+ deparseAppendStringInfoString(state, "FIRST ");
+ }
+ else if (fetch_stmt->howMany == -1)
+ {
+ deparseAppendStringInfoString(state, "LAST ");
+ }
+ else
+ {
+ deparseAppendStringInfo(state, "ABSOLUTE %ld ", fetch_stmt->howMany);
+ }
+ break;
+ case FETCH_RELATIVE:
+ deparseAppendStringInfo(state, "RELATIVE %ld ", fetch_stmt->howMany);
+ }
+
+ deparseAppendStringInfoString(state, quote_identifier(fetch_stmt->portalname));
+}
+
+static void deparseAlterDefaultPrivilegesStmt(DeparseState *state, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER DEFAULT PRIVILEGES ");
+
+ foreach (lc, alter_default_privileges_stmt->options)
+ {
+ DefElem *defelem = castNode(DefElem, lfirst(lc));
+ if (strcmp(defelem->defname, "schemas") == 0)
+ {
+ deparseAppendStringInfoString(state, "IN SCHEMA ");
+ deparseNameList(state, castNode(List, defelem->arg));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (strcmp(defelem->defname, "roles") == 0)
+ {
+ deparseAppendStringInfoString(state, "FOR ROLE ");
+ deparseRoleList(state, castNode(List, defelem->arg));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else
+ {
+ // No other DefElems are supported
+ Assert(false);
+ }
+ }
+
+ deparseGrantStmt(state, alter_default_privileges_stmt->action);
+}
+
+static void deparseReindexStmt(DeparseState *state, ReindexStmt *reindex_stmt)
+{
+ deparseAppendStringInfoString(state, "REINDEX ");
+
+ deparseUtilityOptionList(state, reindex_stmt->params);
+
+ switch (reindex_stmt->kind)
+ {
+ case REINDEX_OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case REINDEX_OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case REINDEX_OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case REINDEX_OBJECT_SYSTEM:
+ deparseAppendStringInfoString(state, "SYSTEM ");
+ break;
+ case REINDEX_OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ break;
+ }
+
+ if (reindex_stmt->relation != NULL)
+ {
+ deparseRangeVar(state, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ }
+ else if (reindex_stmt->name != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(reindex_stmt->name));
+ }
+}
+
+static void deparseRuleStmt(DeparseState *state, RuleStmt* rule_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ if (rule_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ deparseAppendStringInfoString(state, "RULE ");
+ deparseAppendStringInfoString(state, quote_identifier(rule_stmt->rulename));
+ deparseAppendStringInfoString(state, " AS ON ");
+
+ switch (rule_stmt->event)
+ {
+ case CMD_UNKNOWN:
+ case CMD_UTILITY:
+ case CMD_NOTHING:
+ // Not supported here
+ Assert(false);
+ break;
+ case CMD_SELECT:
+ deparseAppendStringInfoString(state, "SELECT ");
+ break;
+ case CMD_UPDATE:
+ deparseAppendStringInfoString(state, "UPDATE ");
+ break;
+ case CMD_INSERT:
+ deparseAppendStringInfoString(state, "INSERT ");
+ break;
+ case CMD_DELETE:
+ deparseAppendStringInfoString(state, "DELETE ");
+ break;
+ case CMD_MERGE:
+ deparseAppendStringInfoString(state, "MERGE ");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "TO ");
+ deparseRangeVar(state, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseWhereClause(state, rule_stmt->whereClause);
+
+ deparseAppendStringInfoString(state, "DO ");
+
+ if (rule_stmt->instead)
+ deparseAppendStringInfoString(state, "INSTEAD ");
+
+ if (list_length(rule_stmt->actions) == 0)
+ {
+ deparseAppendStringInfoString(state, "NOTHING");
+ }
+ else if (list_length(rule_stmt->actions) == 1)
+ {
+ deparseRuleActionStmt(state, linitial(rule_stmt->actions));
+ }
+ else
+ {
+ deparseAppendStringInfoChar(state, '(');
+ foreach (lc, rule_stmt->actions)
+ {
+ deparseRuleActionStmt(state, lfirst(lc));
+ if (lnext(rule_stmt->actions, lc))
+ deparseAppendStringInfoString(state, "; ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+static void deparseNotifyStmt(DeparseState *state, NotifyStmt *notify_stmt)
+{
+ deparseAppendStringInfoString(state, "NOTIFY ");
+ deparseAppendStringInfoString(state, quote_identifier(notify_stmt->conditionname));
+
+ if (notify_stmt->payload != NULL)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ deparseStringLiteral(state, notify_stmt->payload);
+ }
+}
+
+static void deparseListenStmt(DeparseState *state, ListenStmt *listen_stmt)
+{
+ deparseAppendStringInfoString(state, "LISTEN ");
+ deparseAppendStringInfoString(state, quote_identifier(listen_stmt->conditionname));
+}
+
+static void deparseUnlistenStmt(DeparseState *state, UnlistenStmt *unlisten_stmt)
+{
+ deparseAppendStringInfoString(state, "UNLISTEN ");
+ if (unlisten_stmt->conditionname == NULL)
+ deparseAppendStringInfoString(state, "*");
+ else
+ deparseAppendStringInfoString(state, quote_identifier(unlisten_stmt->conditionname));
+}
+
+static void deparseCreateSeqStmt(DeparseState *state, CreateSeqStmt *create_seq_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+
+ deparseOptTemp(state, create_seq_stmt->sequence->relpersistence);
+
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+
+ if (create_seq_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseRangeVar(state, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseOptSeqOptList(state, create_seq_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterFunctionStmt(DeparseState *state, AlterFunctionStmt *alter_function_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (alter_function_stmt->objtype)
+ {
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ default:
+ // Not supported here
+ Assert(false);
+ break;
+ }
+
+ deparseFunctionWithArgtypes(state, alter_function_stmt->func);
+ deparseAppendStringInfoChar(state, ' ');
+
+ foreach (lc, alter_function_stmt->actions)
+ {
+ deparseCommonFuncOptItem(state, castNode(DefElem, lfirst(lc)));
+ if (lnext(alter_function_stmt->actions, lc))
+ deparseAppendStringInfoChar(state, ' ');
+ }
+}
+
+static void deparseTruncateStmt(DeparseState *state, TruncateStmt *truncate_stmt)
+{
+ deparseAppendStringInfoString(state, "TRUNCATE ");
+
+ deparseRelationExprList(state, truncate_stmt->relations);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (truncate_stmt->restart_seqs)
+ deparseAppendStringInfoString(state, "RESTART IDENTITY ");
+
+ deparseOptDropBehavior(state, truncate_stmt->behavior);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateEventTrigStmt(DeparseState *state, CreateEventTrigStmt *create_event_trig_stmt)
+{
+ ListCell *lc = NULL;
+ ListCell *lc2 = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE EVENT TRIGGER ");
+ deparseAppendStringInfoString(state, quote_identifier(create_event_trig_stmt->trigname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "ON ");
+ deparseAppendStringInfoString(state, quote_identifier(create_event_trig_stmt->eventname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_event_trig_stmt->whenclause)
+ {
+ deparseAppendStringInfoString(state, "WHEN ");
+
+ foreach (lc, create_event_trig_stmt->whenclause)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ List *l = castNode(List, def_elem->arg);
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoString(state, " IN (");
+ foreach (lc2, l)
+ {
+ deparseStringLiteral(state, strVal(lfirst(lc2)));
+ if (lnext(l, lc2))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+ if (lnext(create_event_trig_stmt->whenclause, lc))
+ deparseAppendStringInfoString(state, " AND ");
+ }
+
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "EXECUTE FUNCTION ");
+ deparseFuncName(state, create_event_trig_stmt->funcname);
+ deparseAppendStringInfoString(state, "()");
+}
+
+static void deparseAlterEventTrigStmt(DeparseState *state, AlterEventTrigStmt *alter_event_trig_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER EVENT TRIGGER ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_event_trig_stmt->trigname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (alter_event_trig_stmt->tgenabled)
+ {
+ case TRIGGER_FIRES_ON_ORIGIN:
+ deparseAppendStringInfoString(state, "ENABLE");
+ break;
+ case TRIGGER_FIRES_ON_REPLICA:
+ deparseAppendStringInfoString(state, "ENABLE REPLICA");
+ break;
+ case TRIGGER_FIRES_ALWAYS:
+ deparseAppendStringInfoString(state, "ENABLE ALWAYS");
+ break;
+ case TRIGGER_DISABLED:
+ deparseAppendStringInfoString(state, "DISABLE");
+ break;
+ }
+}
+
+static void deparseRefreshMatViewStmt(DeparseState *state, RefreshMatViewStmt *refresh_mat_view_stmt)
+{
+ deparseAppendStringInfoString(state, "REFRESH MATERIALIZED VIEW ");
+
+ if (refresh_mat_view_stmt->concurrent)
+ deparseAppendStringInfoString(state, "CONCURRENTLY ");
+
+ deparseRangeVar(state, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (refresh_mat_view_stmt->skipData)
+ deparseAppendStringInfoString(state, "WITH NO DATA ");
+
+ removeTrailingSpace(state);
+}
+
+static void deparseReplicaIdentityStmt(DeparseState *state, ReplicaIdentityStmt *replica_identity_stmt)
+{
+ switch (replica_identity_stmt->identity_type)
+ {
+ case REPLICA_IDENTITY_NOTHING:
+ deparseAppendStringInfoString(state, "NOTHING ");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ deparseAppendStringInfoString(state, "FULL ");
+ break;
+ case REPLICA_IDENTITY_DEFAULT:
+ deparseAppendStringInfoString(state, "DEFAULT ");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ Assert(replica_identity_stmt->name != NULL);
+ deparseAppendStringInfoString(state, "USING INDEX ");
+ deparseAppendStringInfoString(state, quote_identifier(replica_identity_stmt->name));
+ break;
+ }
+}
+
+// "CreatePolicyStmt" in gram.y
+static void deparseCreatePolicyStmt(DeparseState *state, CreatePolicyStmt *create_policy_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE POLICY ");
+ deparseColId(state, create_policy_stmt->policy_name);
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (!create_policy_stmt->permissive)
+ deparseAppendStringInfoString(state, "AS RESTRICTIVE ");
+
+ if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
+ Assert(true); // Default
+ else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
+ deparseAppendStringInfoString(state, "FOR SELECT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
+ deparseAppendStringInfoString(state, "FOR INSERT ");
+ else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
+ deparseAppendStringInfoString(state, "FOR UPDATE ");
+ else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
+ deparseAppendStringInfoString(state, "FOR DELETE ");
+ else
+ Assert(false);
+
+ deparseAppendStringInfoString(state, "TO ");
+ deparseRoleList(state, create_policy_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_policy_stmt->qual != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING (");
+ deparseExpr(state, create_policy_stmt->qual, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (create_policy_stmt->with_check != NULL)
+ {
+ deparseAppendStringInfoString(state, "WITH CHECK (");
+ deparseExpr(state, create_policy_stmt->with_check, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+}
+
+// "AlterPolicyStmt" in gram.y
+static void deparseAlterPolicyStmt(DeparseState *state, AlterPolicyStmt *alter_policy_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER POLICY ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_policy_stmt->policy_name));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseRangeVar(state, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(alter_policy_stmt->roles) > 0)
+ {
+ deparseAppendStringInfoString(state, "TO ");
+ deparseRoleList(state, alter_policy_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (alter_policy_stmt->qual != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING (");
+ deparseExpr(state, alter_policy_stmt->qual, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (alter_policy_stmt->with_check != NULL)
+ {
+ deparseAppendStringInfoString(state, "WITH CHECK (");
+ deparseExpr(state, alter_policy_stmt->with_check, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+}
+
+static void deparseCreateTableSpaceStmt(DeparseState *state, CreateTableSpaceStmt *create_table_space_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE TABLESPACE ");
+ deparseColId(state, create_table_space_stmt->tablespacename);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_table_space_stmt->owner != NULL)
+ {
+ deparseAppendStringInfoString(state, "OWNER ");
+ deparseRoleSpec(state, create_table_space_stmt->owner);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ deparseAppendStringInfoString(state, "LOCATION ");
+
+ if (create_table_space_stmt->location != NULL)
+ deparseStringLiteral(state, create_table_space_stmt->location);
+ else
+ deparseAppendStringInfoString(state, "''");
+
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseOptWith(state, create_table_space_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateTransformStmt(DeparseState *state, CreateTransformStmt *create_transform_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE ");
+ if (create_transform_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+
+ deparseAppendStringInfoString(state, "TRANSFORM FOR ");
+ deparseTypeName(state, create_transform_stmt->type_name);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseAppendStringInfoString(state, quote_identifier(create_transform_stmt->lang));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoChar(state, '(');
+
+ if (create_transform_stmt->fromsql)
+ {
+ deparseAppendStringInfoString(state, "FROM SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(state, create_transform_stmt->fromsql);
+ }
+
+ if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
+ deparseAppendStringInfoString(state, ", ");
+
+ if (create_transform_stmt->tosql)
+ {
+ deparseAppendStringInfoString(state, "TO SQL WITH FUNCTION ");
+ deparseFunctionWithArgtypes(state, create_transform_stmt->tosql);
+ }
+
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseCreateAmStmt(DeparseState *state, CreateAmStmt *create_am_stmt)
+{
+ deparseAppendStringInfoString(state, "CREATE ACCESS METHOD ");
+ deparseAppendStringInfoString(state, quote_identifier(create_am_stmt->amname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "TYPE ");
+ switch (create_am_stmt->amtype)
+ {
+ case AMTYPE_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case AMTYPE_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ }
+
+ deparseAppendStringInfoString(state, "HANDLER ");
+ deparseHandlerName(state, create_am_stmt->handler_name);
+}
+
+// "pub_obj_list" in gram.y
+static void deparsePublicationObjectList(DeparseState *state, List *pubobjects) {
+ const ListCell *lc;
+ foreach(lc, pubobjects) {
+ PublicationObjSpec *obj = lfirst(lc);
+
+ switch (obj->pubobjtype) {
+ case PUBLICATIONOBJ_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ deparseRangeVar(state, obj->pubtable->relation, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (obj->pubtable->columns)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseColumnList(state, obj->pubtable->columns);
+ deparseAppendStringInfoChar(state, ')');
+ }
+
+ if (obj->pubtable->whereClause)
+ {
+ deparseAppendStringInfoString(state, " WHERE (");
+ deparseExpr(state, obj->pubtable->whereClause, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ")");
+ }
+
+ break;
+ case PUBLICATIONOBJ_TABLES_IN_SCHEMA:
+ deparseAppendStringInfoString(state, "TABLES IN SCHEMA ");
+ deparseAppendStringInfoString(state, quote_identifier(obj->name));
+ break;
+ case PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA:
+ deparseAppendStringInfoString(state, "TABLES IN SCHEMA CURRENT_SCHEMA");
+ break;
+ case PUBLICATIONOBJ_CONTINUATION:
+ // This should be unreachable, the parser merges these before we can even get here.
+ Assert(false);
+ break;
+ }
+
+ if (lnext(pubobjects, lc)) {
+ deparseAppendStringInfoString(state, ", ");
+ }
+ }
+}
+
+static void deparseCreatePublicationStmt(DeparseState *state, CreatePublicationStmt *create_publication_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "CREATE PUBLICATION ");
+ deparseAppendStringInfoString(state, quote_identifier(create_publication_stmt->pubname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(create_publication_stmt->pubobjects) > 0)
+ {
+ deparseAppendStringInfoString(state, "FOR ");
+ deparsePublicationObjectList(state, create_publication_stmt->pubobjects);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ else if (create_publication_stmt->for_all_tables)
+ {
+ deparseAppendStringInfoString(state, "FOR ALL TABLES ");
+ }
+
+ deparseOptDefinition(state, create_publication_stmt->options);
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterPublicationStmt(DeparseState *state, AlterPublicationStmt *alter_publication_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER PUBLICATION ");
+ deparseColId(state, alter_publication_stmt->pubname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(alter_publication_stmt->pubobjects) > 0)
+ {
+ switch (alter_publication_stmt->action)
+ {
+ case AP_SetObjects:
+ deparseAppendStringInfoString(state, "SET ");
+ break;
+ case AP_AddObjects:
+ deparseAppendStringInfoString(state, "ADD ");
+ break;
+ case AP_DropObjects:
+ deparseAppendStringInfoString(state, "DROP ");
+ break;
+ }
+
+ deparsePublicationObjectList(state, alter_publication_stmt->pubobjects);
+ }
+ else if (list_length(alter_publication_stmt->options) > 0)
+ {
+ deparseAppendStringInfoString(state, "SET ");
+ deparseDefinition(state, alter_publication_stmt->options);
+ }
+ else
+ {
+ Assert(false);
+ }
+}
+
+static void deparseAlterSeqStmt(DeparseState *state, AlterSeqStmt *alter_seq_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER SEQUENCE ");
+
+ if (alter_seq_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseRangeVar(state, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseSeqOptList(state, alter_seq_stmt->options);
+
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterSystemStmt(DeparseState *state, AlterSystemStmt *alter_system_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER SYSTEM ");
+ deparseVariableSetStmt(state, alter_system_stmt->setstmt);
+}
+
+static void deparseCommentStmt(DeparseState *state, CommentStmt *comment_stmt)
+{
+ ListCell *lc;
+ List *l;
+
+ deparseAppendStringInfoString(state, "COMMENT ON ");
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ deparseAppendStringInfoString(state, "COLUMN ");
+ break;
+ case OBJECT_INDEX:
+ deparseAppendStringInfoString(state, "INDEX ");
+ break;
+ case OBJECT_SEQUENCE:
+ deparseAppendStringInfoString(state, "SEQUENCE ");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ break;
+ case OBJECT_TABLE:
+ deparseAppendStringInfoString(state, "TABLE ");
+ break;
+ case OBJECT_VIEW:
+ deparseAppendStringInfoString(state, "VIEW ");
+ break;
+ case OBJECT_MATVIEW:
+ deparseAppendStringInfoString(state, "MATERIALIZED VIEW ");
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ deparseAppendStringInfoString(state, "FOREIGN TABLE ");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ break;
+ case OBJECT_TSPARSER:
+ deparseAppendStringInfoString(state, "TEXT SEARCH PARSER ");
+ break;
+ case OBJECT_TSTEMPLATE:
+ deparseAppendStringInfoString(state, "TEXT SEARCH TEMPLATE ");
+ break;
+ case OBJECT_ACCESS_METHOD:
+ deparseAppendStringInfoString(state, "ACCESS METHOD ");
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ break;
+ case OBJECT_EXTENSION:
+ deparseAppendStringInfoString(state, "EXTENSION ");
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ break;
+ case OBJECT_ROLE:
+ deparseAppendStringInfoString(state, "ROLE ");
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseAppendStringInfoString(state, "SUBSCRIPTION ");
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ break;
+ case OBJECT_TABCONSTRAINT:
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ break;
+ case OBJECT_POLICY:
+ deparseAppendStringInfoString(state, "POLICY ");
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ break;
+ case OBJECT_RULE:
+ deparseAppendStringInfoString(state, "RULE ");
+ break;
+ case OBJECT_TRANSFORM:
+ deparseAppendStringInfoString(state, "TRANSFORM ");
+ break;
+ case OBJECT_TRIGGER:
+ deparseAppendStringInfoString(state, "TRIGGER ");
+ break;
+ case OBJECT_OPCLASS:
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ break;
+ case OBJECT_OPFAMILY:
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECT ");
+ break;
+ case OBJECT_CAST:
+ deparseAppendStringInfoString(state, "CAST ");
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ switch (comment_stmt->objtype)
+ {
+ case OBJECT_COLUMN:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ deparseAnyName(state, castNode(List, comment_stmt->object));
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, quote_identifier(strVal(comment_stmt->object)));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ deparseTypeName(state, castNode(TypeName, comment_stmt->object));
+ break;
+ case OBJECT_AGGREGATE:
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_OPERATOR:
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, comment_stmt->object));
+ break;
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ l = castNode(List, comment_stmt->object);
+ deparseAppendStringInfoString(state, quote_identifier(strVal(llast(l))));
+ deparseAppendStringInfoString(state, " ON ");
+ deparseAnyNameSkipLast(state, l);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ l = castNode(List, comment_stmt->object);
+ deparseAppendStringInfoString(state, quote_identifier(strVal(llast(l))));
+ deparseAppendStringInfoString(state, " ON DOMAIN ");
+ deparseTypeName(state, linitial(l));
+ break;
+ case OBJECT_TRANSFORM:
+ l = castNode(List, comment_stmt->object);
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " LANGUAGE ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(lsecond(l))));
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ l = castNode(List, comment_stmt->object);
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseAppendStringInfoString(state, quote_identifier(strVal(linitial(l))));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseValue(state, (union ValUnion *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case OBJECT_CAST:
+ l = castNode(List, comment_stmt->object);
+ deparseAppendStringInfoChar(state, '(');
+ deparseTypeName(state, castNode(TypeName, linitial(l)));
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, castNode(TypeName, lsecond(l)));
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ default:
+ // No other cases are supported in the parser
+ Assert(false);
+ break;
+ }
+
+ deparseAppendStringInfoString(state, " IS ");
+
+ if (comment_stmt->comment != NULL)
+ deparseStringLiteral(state, comment_stmt->comment);
+ else
+ deparseAppendStringInfoString(state, "NULL");
+}
+
+// "stats_param" in gram.y
+static void deparseStatsElem(DeparseState *state, StatsElem *stats_elem)
+{
+ // only one of stats_elem->name or stats_elem->expr can be non-null
+ if (stats_elem->name)
+ deparseAppendStringInfoString(state, stats_elem->name);
+ else if (stats_elem->expr)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, stats_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ }
+}
+
+static void deparseCreateStatsStmt(DeparseState *state, CreateStatsStmt *create_stats_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE STATISTICS ");
+
+ if (create_stats_stmt->if_not_exists)
+ deparseAppendStringInfoString(state, "IF NOT EXISTS ");
+
+ deparseAnyName(state, create_stats_stmt->defnames);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (list_length(create_stats_stmt->stat_types) > 0)
+ {
+ deparseAppendStringInfoChar(state, '(');
+ deparseNameList(state, create_stats_stmt->stat_types);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseAppendStringInfoString(state, "ON ");
+ foreach (lc, create_stats_stmt->exprs)
+ {
+ deparseStatsElem(state, lfirst(lc));
+ if (lnext(create_stats_stmt->exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseAppendStringInfoString(state, " FROM ");
+ deparseFromList(state, create_stats_stmt->relations);
+}
+
+static void deparseAlterCollationStmt(DeparseState *state, AlterCollationStmt *alter_collation_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER COLLATION ");
+ deparseAnyName(state, alter_collation_stmt->collname);
+ deparseAppendStringInfoString(state, " REFRESH VERSION");
+}
+
+static void deparseAlterDatabaseStmt(DeparseState *state, AlterDatabaseStmt *alter_database_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER DATABASE ");
+ deparseColId(state, alter_database_stmt->dbname);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseCreatedbOptList(state, alter_database_stmt->options);
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterDatabaseSetStmt(DeparseState *state, AlterDatabaseSetStmt *alter_database_set_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER DATABASE ");
+ deparseColId(state, alter_database_set_stmt->dbname);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseVariableSetStmt(state, alter_database_set_stmt->setstmt);
+}
+
+static void deparseAlterStatsStmt(DeparseState *state, AlterStatsStmt *alter_stats_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER STATISTICS ");
+
+ if (alter_stats_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAnyName(state, alter_stats_stmt->defnames);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (alter_stats_stmt->stxstattarget)
+ deparseAppendStringInfo(state, "SET STATISTICS %d", castNode(Integer, alter_stats_stmt->stxstattarget)->ival);
+ else
+ deparseAppendStringInfo(state, "SET STATISTICS DEFAULT");
+}
+
+static void deparseAlterTSDictionaryStmt(DeparseState *state, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER TEXT SEARCH DICTIONARY ");
+
+ deparseAnyName(state, alter_ts_dictionary_stmt->dictname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseDefinition(state, alter_ts_dictionary_stmt->options);
+}
+
+static void deparseAlterTSConfigurationStmt(DeparseState *state, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
+{
+ ListCell *lc = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(state, alter_ts_configuration_stmt->cfgname);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (alter_ts_configuration_stmt->kind)
+ {
+ case ALTER_TSCONFIG_ADD_MAPPING:
+ deparseAppendStringInfoString(state, "ADD MAPPING FOR ");
+ deparseNameList(state, alter_ts_configuration_stmt->tokentype);
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyNameList(state, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+ deparseAppendStringInfoString(state, "ALTER MAPPING FOR ");
+ deparseNameList(state, alter_ts_configuration_stmt->tokentype);
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyNameList(state, alter_ts_configuration_stmt->dicts);
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT:
+ deparseAppendStringInfoString(state, "ALTER MAPPING REPLACE ");
+ deparseAnyName(state, linitial(alter_ts_configuration_stmt->dicts));
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyName(state, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+ deparseAppendStringInfoString(state, "ALTER MAPPING FOR ");
+ deparseNameList(state, alter_ts_configuration_stmt->tokentype);
+ deparseAppendStringInfoString(state, " REPLACE ");
+ deparseAnyName(state, linitial(alter_ts_configuration_stmt->dicts));
+ deparseAppendStringInfoString(state, " WITH ");
+ deparseAnyName(state, lsecond(alter_ts_configuration_stmt->dicts));
+ break;
+ case ALTER_TSCONFIG_DROP_MAPPING:
+ deparseAppendStringInfoString(state, "DROP MAPPING ");
+ if (alter_ts_configuration_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+ deparseAppendStringInfoString(state, "FOR ");
+ deparseNameList(state, alter_ts_configuration_stmt->tokentype);
+ break;
+ }
+}
+
+static void deparseVariableShowStmt(DeparseState *state, VariableShowStmt *variable_show_stmt)
+{
+ deparseAppendStringInfoString(state, "SHOW ");
+
+ if (strcmp(variable_show_stmt->name, "timezone") == 0)
+ deparseAppendStringInfoString(state, "TIME ZONE");
+ else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
+ deparseAppendStringInfoString(state, "TRANSACTION ISOLATION LEVEL");
+ else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
+ deparseAppendStringInfoString(state, "SESSION AUTHORIZATION");
+ else if (strcmp(variable_show_stmt->name, "all") == 0)
+ deparseAppendStringInfoString(state, "ALL");
+ else
+ deparseAppendStringInfoString(state, quote_identifier(variable_show_stmt->name));
+}
+
+// "tablesample_clause" in gram.y
+static void deparseRangeTableSample(DeparseState *state, RangeTableSample *range_table_sample)
+{
+ deparseRangeVar(state, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
+
+ deparseAppendStringInfoString(state, " TABLESAMPLE ");
+
+ deparseFuncName(state, range_table_sample->method);
+ deparseAppendStringInfoChar(state, '(');
+ deparseExprList(state, range_table_sample->args);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (range_table_sample->repeatable != NULL)
+ {
+ deparseAppendStringInfoString(state, "REPEATABLE (");
+ deparseExpr(state, range_table_sample->repeatable, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseCreateSubscriptionStmt(DeparseState *state, CreateSubscriptionStmt *create_subscription_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "CREATE SUBSCRIPTION ");
+ deparseAppendStringInfoString(state, quote_identifier(create_subscription_stmt->subname));
+
+ deparseAppendStringInfoString(state, " CONNECTION ");
+ if (create_subscription_stmt->conninfo != NULL)
+ deparseStringLiteral(state, create_subscription_stmt->conninfo);
+ else
+ deparseAppendStringInfoString(state, "''");
+
+ deparseAppendStringInfoString(state, " PUBLICATION ");
+
+ foreach(lc, create_subscription_stmt->publication)
+ {
+ deparseColLabel(state, strVal(lfirst(lc)));
+ if (lnext(create_subscription_stmt->publication, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseOptDefinition(state, create_subscription_stmt->options);
+ removeTrailingSpace(state);
+}
+
+static void deparseAlterSubscriptionStmt(DeparseState *state, AlterSubscriptionStmt *alter_subscription_stmt)
+{
+ ListCell *lc;
+
+ deparseAppendStringInfoString(state, "ALTER SUBSCRIPTION ");
+ deparseAppendStringInfoString(state, quote_identifier(alter_subscription_stmt->subname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (alter_subscription_stmt->kind)
+ {
+ case ALTER_SUBSCRIPTION_OPTIONS:
+ deparseAppendStringInfoString(state, "SET ");
+ deparseDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SKIP:
+ deparseAppendStringInfoString(state, "SKIP ");
+ deparseDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_CONNECTION:
+ deparseAppendStringInfoString(state, "CONNECTION ");
+ deparseStringLiteral(state, alter_subscription_stmt->conninfo);
+ deparseAppendStringInfoChar(state, ' ');
+ break;
+ case ALTER_SUBSCRIPTION_REFRESH:
+ deparseAppendStringInfoString(state, "REFRESH PUBLICATION ");
+ deparseOptDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ADD_PUBLICATION:
+ deparseAppendStringInfoString(state, "ADD PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(state, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ deparseOptDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_DROP_PUBLICATION:
+ deparseAppendStringInfoString(state, "DROP PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(state, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ deparseOptDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_SET_PUBLICATION:
+ deparseAppendStringInfoString(state, "SET PUBLICATION ");
+ foreach(lc, alter_subscription_stmt->publication)
+ {
+ deparseColLabel(state, strVal(lfirst(lc)));
+ if (lnext(alter_subscription_stmt->publication, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+ deparseOptDefinition(state, alter_subscription_stmt->options);
+ break;
+ case ALTER_SUBSCRIPTION_ENABLED:
+ Assert(list_length(alter_subscription_stmt->options) == 1);
+ DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
+ Assert(strcmp(defelem->defname, "enabled") == 0);
+ if (optBooleanValue(defelem->arg))
+ {
+ deparseAppendStringInfoString(state, " ENABLE ");
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, " DISABLE ");
+ }
+ break;
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseDropSubscriptionStmt(DeparseState *state, DropSubscriptionStmt *drop_subscription_stmt)
+{
+ deparseAppendStringInfoString(state, "DROP SUBSCRIPTION ");
+
+ if (drop_subscription_stmt->missing_ok)
+ deparseAppendStringInfoString(state, "IF EXISTS ");
+
+ deparseAppendStringInfoString(state, drop_subscription_stmt->subname);
+}
+
+static void deparseCallStmt(DeparseState *state, CallStmt *call_stmt)
+{
+ deparseAppendStringInfoString(state, "CALL ");
+ deparseFuncCall(state, call_stmt->funccall, DEPARSE_NODE_CONTEXT_NONE);
+}
+
+static void deparseAlterOwnerStmt(DeparseState *state, AlterOwnerStmt *alter_owner_stmt)
+{
+ List *l = NULL;
+
+ deparseAppendStringInfoString(state, "ALTER ");
+
+ switch (alter_owner_stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ deparseAppendStringInfoString(state, "AGGREGATE ");
+ deparseAggregateWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_COLLATION:
+ deparseAppendStringInfoString(state, "COLLATION ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_CONVERSION:
+ deparseAppendStringInfoString(state, "CONVERSION ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_DATABASE:
+ deparseAppendStringInfoString(state, "DATABASE ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_DOMAIN:
+ deparseAppendStringInfoString(state, "DOMAIN ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FUNCTION:
+ deparseAppendStringInfoString(state, "FUNCTION ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_LANGUAGE:
+ deparseAppendStringInfoString(state, "LANGUAGE ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_LARGEOBJECT:
+ deparseAppendStringInfoString(state, "LARGE OBJECT ");
+ deparseNumericOnly(state, (union ValUnion *) alter_owner_stmt->object);
+ break;
+ case OBJECT_OPERATOR:
+ deparseAppendStringInfoString(state, "OPERATOR ");
+ deparseOperatorWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_OPCLASS:
+ l = castNode(List, alter_owner_stmt->object);
+ deparseAppendStringInfoString(state, "OPERATOR CLASS ");
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseColId(state, strVal(linitial(l)));
+ break;
+ case OBJECT_OPFAMILY:
+ l = castNode(List, alter_owner_stmt->object);
+ deparseAppendStringInfoString(state, "OPERATOR FAMILY ");
+ deparseAnyNameSkipFirst(state, l);
+ deparseAppendStringInfoString(state, " USING ");
+ deparseColId(state, strVal(linitial(l)));
+ break;
+ case OBJECT_PROCEDURE:
+ deparseAppendStringInfoString(state, "PROCEDURE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_ROUTINE:
+ deparseAppendStringInfoString(state, "ROUTINE ");
+ deparseFunctionWithArgtypes(state, castNode(ObjectWithArgs, alter_owner_stmt->object));
+ break;
+ case OBJECT_SCHEMA:
+ deparseAppendStringInfoString(state, "SCHEMA ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_TYPE:
+ deparseAppendStringInfoString(state, "TYPE ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TABLESPACE:
+ deparseAppendStringInfoString(state, "TABLESPACE ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ deparseAppendStringInfoString(state, "STATISTICS ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ deparseAppendStringInfoString(state, "TEXT SEARCH DICTIONARY ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ deparseAppendStringInfoString(state, "TEXT SEARCH CONFIGURATION ");
+ deparseAnyName(state, castNode(List, alter_owner_stmt->object));
+ break;
+ case OBJECT_FDW:
+ deparseAppendStringInfoString(state, "FOREIGN DATA WRAPPER ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ deparseAppendStringInfoString(state, "SERVER ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ deparseAppendStringInfoString(state, "EVENT TRIGGER ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_PUBLICATION:
+ deparseAppendStringInfoString(state, "PUBLICATION ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ deparseAppendStringInfoString(state, "SUBSCRIPTION ");
+ deparseColId(state, strVal(alter_owner_stmt->object));
+ break;
+ default:
+ Assert(false);
+ }
+
+ deparseAppendStringInfoString(state, " OWNER TO ");
+ deparseRoleSpec(state, alter_owner_stmt->newowner);
+}
+
+// "operator_def_list" in gram.y
+static void deparseOperatorDefList(DeparseState *state, List *defs)
+{
+ ListCell *lc = NULL;
+
+ foreach (lc, defs)
+ {
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
+ deparseAppendStringInfoString(state, quote_identifier(def_elem->defname));
+ deparseAppendStringInfoString(state, " = ");
+ if (def_elem->arg != NULL)
+ deparseDefArg(state, def_elem->arg, true);
+ else
+ deparseAppendStringInfoString(state, "NONE");
+
+ if (lnext(defs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+}
+
+static void deparseAlterOperatorStmt(DeparseState *state, AlterOperatorStmt *alter_operator_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER OPERATOR ");
+ deparseOperatorWithArgtypes(state, alter_operator_stmt->opername);
+ deparseAppendStringInfoString(state, " SET (");
+ deparseOperatorDefList(state, alter_operator_stmt->options);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseAlterTypeStmt(DeparseState *state, AlterTypeStmt *alter_type_stmt)
+{
+ deparseAppendStringInfoString(state, "ALTER TYPE ");
+ deparseAnyName(state, alter_type_stmt->typeName);
+ deparseAppendStringInfoString(state, " SET (");
+ deparseOperatorDefList(state, alter_type_stmt->options);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseDropOwnedStmt(DeparseState *state, DropOwnedStmt *drop_owned_stmt)
+{
+ deparseAppendStringInfoString(state, "DROP OWNED BY ");
+ deparseRoleList(state, drop_owned_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseOptDropBehavior(state, drop_owned_stmt->behavior);
+ removeTrailingSpace(state);
+}
+
+static void deparseReassignOwnedStmt(DeparseState *state, ReassignOwnedStmt *reassigned_owned_stmt)
+{
+ deparseAppendStringInfoString(state, "REASSIGN OWNED BY ");
+
+ deparseRoleList(state, reassigned_owned_stmt->roles);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseAppendStringInfoString(state, "TO ");
+ deparseRoleSpec(state, reassigned_owned_stmt->newrole);
+}
+
+static void deparseClosePortalStmt(DeparseState *state, ClosePortalStmt *close_portal_stmt)
+{
+ deparseAppendStringInfoString(state, "CLOSE ");
+ if (close_portal_stmt->portalname != NULL)
+ {
+ deparseAppendStringInfoString(state, quote_identifier(close_portal_stmt->portalname));
+ }
+ else
+ {
+ deparseAppendStringInfoString(state, "ALL");
+ }
+}
+
+// "CreateTrigStmt" in gram.y
+static void deparseCreateTrigStmt(DeparseState *state, CreateTrigStmt *create_trig_stmt)
+{
+ ListCell *lc;
+ bool skip_events_or = true;
+
+ deparseAppendStringInfoString(state, "CREATE ");
+ if (create_trig_stmt->replace)
+ deparseAppendStringInfoString(state, "OR REPLACE ");
+ if (create_trig_stmt->isconstraint)
+ deparseAppendStringInfoString(state, "CONSTRAINT ");
+ deparseAppendStringInfoString(state, "TRIGGER ");
+
+ deparseAppendStringInfoString(state, quote_identifier(create_trig_stmt->trigname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (create_trig_stmt->timing)
+ {
+ case TRIGGER_TYPE_BEFORE:
+ deparseAppendStringInfoString(state, "BEFORE ");
+ break;
+ case TRIGGER_TYPE_AFTER:
+ deparseAppendStringInfoString(state, "AFTER ");
+ break;
+ case TRIGGER_TYPE_INSTEAD:
+ deparseAppendStringInfoString(state, "INSTEAD OF ");
+ break;
+ default:
+ Assert(false);
+ }
+
+ if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
+ {
+ deparseAppendStringInfoString(state, "INSERT ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ deparseAppendStringInfoString(state, "OR ");
+ deparseAppendStringInfoString(state, "DELETE ");
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ deparseAppendStringInfoString(state, "OR ");
+ deparseAppendStringInfoString(state, "UPDATE ");
+ if (list_length(create_trig_stmt->columns) > 0)
+ {
+ deparseAppendStringInfoString(state, "OF ");
+ deparseColumnList(state, create_trig_stmt->columns);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ skip_events_or = false;
+ }
+ if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
+ {
+ if (!skip_events_or)
+ deparseAppendStringInfoString(state, "OR ");
+ deparseAppendStringInfoString(state, "TRUNCATE ");
+ }
+
+ deparseAppendStringInfoString(state, "ON ");
+ deparseRangeVar(state, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (create_trig_stmt->transitionRels != NULL)
+ {
+ deparseAppendStringInfoString(state, "REFERENCING ");
+ foreach(lc, create_trig_stmt->transitionRels)
+ {
+ deparseTriggerTransition(state, castNode(TriggerTransition, lfirst(lc)));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+ }
+
+ if (create_trig_stmt->constrrel != NULL)
+ {
+ deparseAppendStringInfoString(state, "FROM ");
+ deparseRangeVar(state, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (create_trig_stmt->deferrable)
+ deparseAppendStringInfoString(state, "DEFERRABLE ");
+
+ if (create_trig_stmt->initdeferred)
+ deparseAppendStringInfoString(state, "INITIALLY DEFERRED ");
+
+ if (create_trig_stmt->row)
+ deparseAppendStringInfoString(state, "FOR EACH ROW ");
+
+ if (create_trig_stmt->whenClause)
+ {
+ deparseAppendStringInfoString(state, "WHEN (");
+ deparseExpr(state, create_trig_stmt->whenClause, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ deparseAppendStringInfoString(state, "EXECUTE FUNCTION ");
+ deparseFuncName(state, create_trig_stmt->funcname);
+ deparseAppendStringInfoChar(state, '(');
+ foreach(lc, create_trig_stmt->args)
+ {
+ deparseStringLiteral(state, strVal(lfirst(lc)));
+ if (lnext(create_trig_stmt->args, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseTriggerTransition(DeparseState *state, TriggerTransition *trigger_transition)
+{
+ if (trigger_transition->isNew)
+ deparseAppendStringInfoString(state, "NEW ");
+ else
+ deparseAppendStringInfoString(state, "OLD ");
+
+ if (trigger_transition->isTable)
+ deparseAppendStringInfoString(state, "TABLE ");
+ else
+ deparseAppendStringInfoString(state, "ROW ");
+
+ deparseAppendStringInfoString(state, quote_identifier(trigger_transition->name));
+}
+
+static void deparseXmlExpr(DeparseState *state, XmlExpr* xml_expr, DeparseNodeContext context)
+{
+ switch (xml_expr->op)
+ {
+ case IS_XMLCONCAT: /* XMLCONCAT(args) */
+ deparseAppendStringInfoString(state, "xmlconcat(");
+ deparseExprList(state, xml_expr->args);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
+ deparseAppendStringInfoString(state, "xmlelement(name ");
+ deparseAppendStringInfoString(state, quote_identifier(xml_expr->name));
+ if (xml_expr->named_args != NULL)
+ {
+ deparseAppendStringInfoString(state, ", xmlattributes(");
+ deparseXmlAttributeList(state, xml_expr->named_args);
+ deparseAppendStringInfoString(state, ")");
+ }
+ if (xml_expr->args != NULL)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ deparseExprList(state, xml_expr->args);
+ }
+ deparseAppendStringInfoString(state, ")");
+ break;
+ case IS_XMLFOREST: /* XMLFOREST(xml_attributes) */
+ deparseAppendStringInfoString(state, "xmlforest(");
+ deparseXmlAttributeList(state, xml_expr->named_args);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
+ Assert(list_length(xml_expr->args) == 2);
+ deparseAppendStringInfoString(state, "xmlparse(");
+ switch (xml_expr->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ deparseAppendStringInfoString(state, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ deparseAppendStringInfoString(state, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(state, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLPI: /* XMLPI(name [, args]) */
+ deparseAppendStringInfoString(state, "xmlpi(name ");
+ deparseAppendStringInfoString(state, quote_identifier(xml_expr->name));
+ if (xml_expr->args != NULL)
+ {
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ }
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
+ deparseAppendStringInfoString(state, "xmlroot(");
+ deparseExpr(state, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ", version ");
+ if (castNode(A_Const, lsecond(xml_expr->args))->isnull)
+ deparseAppendStringInfoString(state, "no value");
+ else
+ deparseExpr(state, lsecond(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
+ if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
+ deparseAppendStringInfoString(state, ", standalone yes");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
+ deparseAppendStringInfoString(state, ", standalone no");
+ else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
+ deparseAppendStringInfoString(state, ", standalone no value");
+ deparseAppendStringInfoChar(state, ')');
+ break;
+ case IS_XMLSERIALIZE: /* XMLSERIALIZE(is_document, xmlval) */
+ // These are represented as XmlSerialize in raw parse trees
+ Assert(false);
+ break;
+ case IS_DOCUMENT: /* xmlval IS DOCUMENT */
+ Assert(list_length(xml_expr->args) == 1);
+ deparseExpr(state, linitial(xml_expr->args), context);
+ deparseAppendStringInfoString(state, " IS DOCUMENT");
+ break;
+ }
+}
+
+// "xmltable_column_el" in gram.y
+static void deparseRangeTableFuncCol(DeparseState *state, RangeTableFuncCol* range_table_func_col)
+{
+ deparseAppendStringInfoString(state, quote_identifier(range_table_func_col->colname));
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (range_table_func_col->for_ordinality)
+ {
+ deparseAppendStringInfoString(state, "FOR ORDINALITY ");
+ }
+ else
+ {
+ deparseTypeName(state, range_table_func_col->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (range_table_func_col->colexpr)
+ {
+ deparseAppendStringInfoString(state, "PATH ");
+ deparseExpr(state, range_table_func_col->colexpr, DEPARSE_NODE_CONTEXT_NONE /* b_expr */);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (range_table_func_col->coldefexpr)
+ {
+ deparseAppendStringInfoString(state, "DEFAULT ");
+ deparseExpr(state, range_table_func_col->coldefexpr, DEPARSE_NODE_CONTEXT_NONE /* b_expr */);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (range_table_func_col->is_not_null)
+ deparseAppendStringInfoString(state, "NOT NULL ");
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "table_ref" and "xmltable" in gram.y
+static void deparseRangeTableFunc(DeparseState *state, RangeTableFunc* range_table_func)
+{
+ ListCell *lc;
+
+ if (range_table_func->lateral)
+ deparseAppendStringInfoString(state, "LATERAL ");
+
+ deparseAppendStringInfoString(state, "xmltable(");
+ if (range_table_func->namespaces)
+ {
+ deparseAppendStringInfoString(state, "xmlnamespaces(");
+ deparseXmlNamespaceList(state, range_table_func->namespaces);
+ deparseAppendStringInfoString(state, "), ");
+ }
+
+ deparseAppendStringInfoChar(state, '(');
+ deparseExpr(state, range_table_func->rowexpr, DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+ deparseAppendStringInfoChar(state, ')');
+
+ deparseAppendStringInfoString(state, " PASSING ");
+ deparseExpr(state, range_table_func->docexpr, DEPARSE_NODE_CONTEXT_NONE /* c_expr */);
+
+ deparseAppendStringInfoString(state, " COLUMNS ");
+ foreach(lc, range_table_func->columns)
+ {
+ deparseRangeTableFuncCol(state, castNode(RangeTableFuncCol, lfirst(lc)));
+ if (lnext(range_table_func->columns, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseAppendStringInfoString(state, ") ");
+
+ if (range_table_func->alias)
+ {
+ deparseAppendStringInfoString(state, "AS ");
+ deparseAlias(state, range_table_func->alias);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseXmlSerialize(DeparseState *state, XmlSerialize *xml_serialize)
+{
+ deparseAppendStringInfoString(state, "xmlserialize(");
+ switch (xml_serialize->xmloption)
+ {
+ case XMLOPTION_DOCUMENT:
+ deparseAppendStringInfoString(state, "document ");
+ break;
+ case XMLOPTION_CONTENT:
+ deparseAppendStringInfoString(state, "content ");
+ break;
+ default:
+ Assert(false);
+ }
+ deparseExpr(state, xml_serialize->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseTypeName(state, xml_serialize->typeName);
+
+ if (xml_serialize->indent) {
+ deparseAppendStringInfoString(state, " INDENT");
+ }
+
+ deparseAppendStringInfoString(state, ")");
+}
+
+static void deparseJsonFormat(DeparseState *state, JsonFormat *json_format)
+{
+ if (json_format == NULL || json_format->format_type == JS_FORMAT_DEFAULT)
+ return;
+
+ deparseAppendStringInfoString(state, "FORMAT JSON ");
+
+ switch (json_format->encoding)
+ {
+ case JS_ENC_UTF8:
+ deparseAppendStringInfoString(state, "ENCODING utf8 ");
+ break;
+ case JS_ENC_UTF16:
+ deparseAppendStringInfoString(state, "ENCODING utf16 ");
+ break;
+ case JS_ENC_UTF32:
+ deparseAppendStringInfoString(state, "ENCODING utf32 ");
+ break;
+ case JS_ENC_DEFAULT:
+ // no encoding specified
+ break;
+ }
+}
+
+static void deparseJsonIsPredicate(DeparseState *state, JsonIsPredicate *j)
+{
+ deparseExpr(state, j->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+
+ deparseJsonFormat(state, castNode(JsonFormat, j->format));
+
+ deparseAppendStringInfoString(state, "IS ");
+
+ switch (j->item_type)
+ {
+ case JS_TYPE_ANY:
+ deparseAppendStringInfoString(state, "JSON ");
+ break;
+ case JS_TYPE_ARRAY:
+ deparseAppendStringInfoString(state, "JSON ARRAY ");
+ break;
+ case JS_TYPE_OBJECT:
+ deparseAppendStringInfoString(state, "JSON OBJECT ");
+ break;
+ case JS_TYPE_SCALAR:
+ deparseAppendStringInfoString(state, "JSON SCALAR ");
+ break;
+ }
+
+ if (j->unique_keys)
+ deparseAppendStringInfoString(state, "WITH UNIQUE ");
+
+ removeTrailingSpace(state);
+}
+
+// "json_value_expr" in gram.y
+static void deparseJsonValueExpr(DeparseState *state, JsonValueExpr *json_value_expr)
+{
+ deparseExpr(state, (Node *) json_value_expr->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonFormat(state, json_value_expr->format);
+}
+
+// "json_value_expr_list" in gram.y
+static void deparseJsonValueExprList(DeparseState *state, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseJsonValueExpr(state, lfirst(lc));
+ removeTrailingSpace(state);
+ if (lnext(exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+}
+
+// "json_name_and_value" in gram.y
+static void deparseJsonKeyValue(DeparseState *state, JsonKeyValue *json_key_value)
+{
+ deparseExpr(state, (Node *) json_key_value->key, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ": ");
+ deparseJsonValueExpr(state, json_key_value->value);
+}
+
+// "json_name_and_value_list" in gram.y
+static void deparseJsonKeyValueList(DeparseState *state, List *exprs)
+{
+ ListCell *lc;
+ foreach(lc, exprs)
+ {
+ deparseJsonKeyValue(state, lfirst(lc));
+ removeTrailingSpace(state);
+ if (lnext(exprs, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+ deparseAppendStringInfoChar(state, ' ');
+}
+
+static void deparseJsonOutput(DeparseState *state, JsonOutput *json_output)
+{
+ if (json_output == NULL)
+ return;
+
+ Assert(json_output->returning != NULL);
+
+ deparseAppendStringInfoString(state, "RETURNING ");
+ deparseTypeName(state, json_output->typeName);
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonFormat(state, json_output->returning->format);
+}
+
+// "json_aggregate_func" and "func_expr" in gram.y
+static void deparseJsonObjectAgg(DeparseState *state, JsonObjectAgg *json_object_agg)
+{
+ Assert(json_object_agg->constructor != NULL);
+
+ deparseAppendStringInfoString(state, "JSON_OBJECTAGG(");
+ deparseJsonKeyValue(state, json_object_agg->arg);
+
+ if (json_object_agg->absent_on_null)
+ deparseAppendStringInfoString(state, "ABSENT ON NULL ");
+
+ if (json_object_agg->unique)
+ deparseAppendStringInfoString(state, "WITH UNIQUE ");
+
+ deparseJsonOutput(state, json_object_agg->constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (json_object_agg->constructor->agg_filter)
+ {
+ deparseAppendStringInfoString(state, "FILTER (WHERE ");
+ deparseExpr(state, json_object_agg->constructor->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (json_object_agg->constructor->over)
+ {
+ struct WindowDef *over = json_object_agg->constructor->over;
+ deparseAppendStringInfoString(state, "OVER ");
+ if (over->name)
+ deparseAppendStringInfoString(state, over->name);
+ else
+ deparseWindowDef(state, over);
+ }
+
+ removeTrailingSpace(state);
+}
+
+// "json_aggregate_func" and "func_expr" in gram.y
+static void deparseJsonArrayAgg(DeparseState *state, JsonArrayAgg *json_array_agg)
+{
+ Assert(json_array_agg->constructor != NULL);
+
+ deparseAppendStringInfoString(state, "JSON_ARRAYAGG(");
+ deparseJsonValueExpr(state, json_array_agg->arg);
+ deparseOptSortClause(state, json_array_agg->constructor->agg_order, DEPARSE_NODE_CONTEXT_NONE);
+
+ if (!json_array_agg->absent_on_null)
+ deparseAppendStringInfoString(state, "NULL ON NULL ");
+
+ deparseJsonOutput(state, json_array_agg->constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoString(state, ") ");
+
+ if (json_array_agg->constructor->agg_filter)
+ {
+ deparseAppendStringInfoString(state, "FILTER (WHERE ");
+ deparseExpr(state, json_array_agg->constructor->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ") ");
+ }
+
+ if (json_array_agg->constructor->over)
+ {
+ struct WindowDef *over = json_array_agg->constructor->over;
+ deparseAppendStringInfoString(state, "OVER ");
+ if (over->name)
+ deparseAppendStringInfoString(state, over->name);
+ else
+ deparseWindowDef(state, over);
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseJsonObjectConstructor(DeparseState *state, JsonObjectConstructor *json_object_constructor)
+{
+ deparseAppendStringInfoString(state, "JSON_OBJECT(");
+ deparseJsonKeyValueList(state, json_object_constructor->exprs);
+
+ if (json_object_constructor->absent_on_null)
+ deparseAppendStringInfoString(state, "ABSENT ON NULL ");
+
+ if (json_object_constructor->unique)
+ deparseAppendStringInfoString(state, "WITH UNIQUE ");
+
+ deparseJsonOutput(state, json_object_constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonArrayConstructor(DeparseState *state, JsonArrayConstructor *json_array_constructor)
+{
+ deparseAppendStringInfoString(state, "JSON_ARRAY(");
+ deparseJsonValueExprList(state, json_array_constructor->exprs);
+
+ if (!json_array_constructor->absent_on_null)
+ deparseAppendStringInfoString(state, "NULL ON NULL ");
+
+ deparseJsonOutput(state, json_array_constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonArrayQueryConstructor(DeparseState *state, JsonArrayQueryConstructor *json_array_query_constructor)
+{
+ deparseAppendStringInfoString(state, "JSON_ARRAY(");
+
+ deparseSelectStmt(state, castNode(SelectStmt, json_array_query_constructor->query), DEPARSE_NODE_CONTEXT_NONE);
+ deparseJsonFormat(state, json_array_query_constructor->format);
+ deparseJsonOutput(state, json_array_query_constructor->output);
+
+ removeTrailingSpace(state);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonParseExpr(DeparseState *state, JsonParseExpr *json_parse_expr)
+{
+ deparseAppendStringInfoString(state, "JSON(");
+
+ deparseJsonValueExpr(state, json_parse_expr->expr);
+
+ if (json_parse_expr->unique_keys)
+ deparseAppendStringInfoString(state, " WITH UNIQUE KEYS");
+
+ deparseAppendStringInfoString(state, ")");
+}
+
+static void deparseJsonScalarExpr(DeparseState *state, JsonScalarExpr *json_scalar_expr)
+{
+ deparseAppendStringInfoString(state, "JSON_SCALAR(");
+ deparseExpr(state, (Node*) json_scalar_expr->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ deparseAppendStringInfoString(state, ")");
+}
+
+static void deparseJsonSerializeExpr(DeparseState *state, JsonSerializeExpr *json_serialize_expr)
+{
+ deparseAppendStringInfoString(state, "JSON_SERIALIZE(");
+
+ deparseJsonValueExpr(state, json_serialize_expr->expr);
+
+ if (json_serialize_expr->output)
+ deparseJsonOutput(state, json_serialize_expr->output);
+
+ deparseAppendStringInfoString(state, ")");
+}
+
+static void deparseJsonQuotesClauseOpt(DeparseState *state, JsonQuotes quotes)
+{
+ switch (quotes)
+ {
+ case JS_QUOTES_UNSPEC:
+ break;
+ case JS_QUOTES_KEEP:
+ deparseAppendStringInfoString(state, " KEEP QUOTES");
+ break;
+ case JS_QUOTES_OMIT:
+ deparseAppendStringInfoString(state, " OMIT QUOTES");
+ break;
+ }
+}
+
+static void deparseJsonOnErrorClauseOpt(DeparseState *state, JsonBehavior *behavior)
+{
+ if (!behavior)
+ return;
+
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonBehavior(state, behavior);
+ deparseAppendStringInfoString(state, " ON ERROR");
+}
+
+static void deparseJsonOnEmptyClauseOpt(DeparseState *state, JsonBehavior *behavior)
+{
+ if (behavior)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonBehavior(state, behavior);
+ deparseAppendStringInfoString(state, " ON EMPTY");
+ }
+}
+
+static void deparseJsonFuncExpr(DeparseState *state, JsonFuncExpr *json_func_expr)
+{
+ switch (json_func_expr->op)
+ {
+ case JSON_EXISTS_OP:
+ deparseAppendStringInfoString(state, "JSON_EXISTS(");
+ break;
+ case JSON_QUERY_OP:
+ deparseAppendStringInfoString(state, "JSON_QUERY(");
+ break;
+ case JSON_VALUE_OP:
+ deparseAppendStringInfoString(state, "JSON_VALUE(");
+ break;
+ case JSON_TABLE_OP:
+ deparseAppendStringInfoString(state, "JSON_TABLE(");
+ break;
+ }
+
+ deparseJsonValueExpr(state, json_func_expr->context_item);
+ deparseAppendStringInfoString(state, ", ");
+ deparseExpr(state, json_func_expr->pathspec, DEPARSE_NODE_CONTEXT_A_EXPR);
+
+ if (json_func_expr->passing)
+ deparseAppendStringInfoString(state, " PASSING ");
+
+ ListCell *lc = NULL;
+ foreach (lc, json_func_expr->passing)
+ {
+ JsonArgument *json_argument = castNode(JsonArgument, lfirst(lc));
+ deparseJsonValueExpr(state, json_argument->val);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseColLabel(state, json_argument->name);
+
+ if (lnext(json_func_expr->passing, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ if (json_func_expr->output)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseJsonOutput(state, json_func_expr->output);
+ }
+
+ switch (json_func_expr->wrapper)
+ {
+ case JSW_UNSPEC:
+ break;
+ case JSW_NONE:
+ deparseAppendStringInfoString(state, " WITHOUT WRAPPER");
+ break;
+ case JSW_CONDITIONAL:
+ deparseAppendStringInfoString(state, " WITH CONDITIONAL WRAPPER");
+ break;
+ case JSW_UNCONDITIONAL:
+ deparseAppendStringInfoString(state, " WITH UNCONDITIONAL WRAPPER");
+ break;
+ }
+
+ deparseJsonQuotesClauseOpt(state, json_func_expr->quotes);
+ deparseJsonOnEmptyClauseOpt(state, json_func_expr->on_empty);
+ deparseJsonOnErrorClauseOpt(state, json_func_expr->on_error);
+
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonTablePathSpec(DeparseState *state, JsonTablePathSpec *json_table_path_spec)
+{
+ deparseStringLiteral(state, castNode(A_Const, json_table_path_spec->string)->val.sval.sval);
+
+ if (json_table_path_spec->name)
+ {
+ deparseAppendStringInfoString(state, " AS ");
+ deparseColLabel(state, json_table_path_spec->name);
+ }
+}
+
+// "json_behavior" in gram.y
+static void deparseJsonBehavior(DeparseState *state, JsonBehavior *json_behavior)
+{
+ switch (json_behavior->btype)
+ {
+ case JSON_BEHAVIOR_NULL:
+ deparseAppendStringInfoString(state, "NULL");
+ break;
+ case JSON_BEHAVIOR_ERROR:
+ deparseAppendStringInfoString(state, "ERROR");
+ break;
+ case JSON_BEHAVIOR_EMPTY:
+ deparseAppendStringInfoString(state, "EMPTY");
+ break;
+ case JSON_BEHAVIOR_TRUE:
+ deparseAppendStringInfoString(state, "TRUE");
+ break;
+ case JSON_BEHAVIOR_FALSE:
+ deparseAppendStringInfoString(state, "FALSE");
+ break;
+ case JSON_BEHAVIOR_EMPTY_ARRAY:
+ deparseAppendStringInfoString(state, "EMPTY ARRAY");
+ break;
+ case JSON_BEHAVIOR_EMPTY_OBJECT:
+ deparseAppendStringInfoString(state, "EMPTY OBJECT");
+ break;
+ case JSON_BEHAVIOR_DEFAULT:
+ deparseAppendStringInfoString(state, "DEFAULT ");
+ deparseExpr(state, (Node*) json_behavior->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
+ break;
+ case JSON_BEHAVIOR_UNKNOWN:
+ deparseAppendStringInfoString(state, "UNKNOWN");
+ break;
+ }
+}
+
+static void deparseJsonTableColumn(DeparseState *state, JsonTableColumn *json_table_column)
+{
+ if (json_table_column->coltype == JTC_NESTED)
+ {
+ deparseAppendStringInfoString(state, "NESTED PATH ");
+ deparseJsonTablePathSpec(state, json_table_column->pathspec);
+ deparseJsonTableColumns(state, json_table_column->columns);
+ return;
+ }
+
+ deparseColLabel(state, json_table_column->name);
+ deparseAppendStringInfoChar(state, ' ');
+
+ switch (json_table_column->coltype)
+ {
+ case JTC_FOR_ORDINALITY:
+ deparseAppendStringInfoString(state, " FOR ORDINALITY");
+ break;
+ case JTC_EXISTS:
+ case JTC_FORMATTED:
+ case JTC_REGULAR:
+ deparseTypeName(state, json_table_column->typeName);
+
+ if (json_table_column->coltype == JTC_EXISTS)
+ deparseAppendStringInfoString(state, " EXISTS ");
+ else
+ deparseAppendStringInfoChar(state, ' ');
+
+ if (json_table_column->format)
+ deparseJsonFormat(state, json_table_column->format);
+
+ if (json_table_column->pathspec)
+ {
+ deparseAppendStringInfoString(state, "PATH ");
+ deparseJsonTablePathSpec(state, json_table_column->pathspec);
+ }
+ break;
+ case JTC_NESTED:
+ Assert(false);
+ }
+
+ switch (json_table_column->wrapper)
+ {
+ case JSW_UNSPEC:
+ break;
+ case JSW_NONE:
+ if (json_table_column->coltype == JTC_REGULAR || json_table_column->coltype == JTC_FORMATTED)
+ deparseAppendStringInfoString(state, " WITHOUT WRAPPER");
+ break;
+ case JSW_CONDITIONAL:
+ deparseAppendStringInfoString(state, " WITH CONDITIONAL WRAPPER");
+ break;
+ case JSW_UNCONDITIONAL:
+ deparseAppendStringInfoString(state, " WITH UNCONDITIONAL WRAPPER");
+ break;
+ }
+
+ deparseJsonQuotesClauseOpt(state, json_table_column->quotes);
+ deparseJsonOnEmptyClauseOpt(state, json_table_column->on_empty);
+ deparseJsonOnErrorClauseOpt(state, json_table_column->on_error);
+}
+
+static void deparseJsonTableColumns(DeparseState *state, List *json_table_columns)
+{
+ deparseAppendStringInfoString(state, " COLUMNS (");
+
+ ListCell *lc = NULL;
+ foreach(lc, json_table_columns)
+ {
+ deparseJsonTableColumn(state, castNode(JsonTableColumn, lfirst(lc)));
+
+ if (lnext(json_table_columns, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseJsonTable(DeparseState *state, JsonTable *json_table)
+{
+ deparseAppendStringInfoString(state, "JSON_TABLE(");
+
+ deparseJsonValueExpr(state, json_table->context_item);
+ deparseAppendStringInfoString(state, ", ");
+ deparseJsonTablePathSpec(state, json_table->pathspec);
+
+ if (json_table->passing)
+ deparseAppendStringInfoString(state, " PASSING ");
+
+ ListCell *lc = NULL;
+ foreach (lc, json_table->passing)
+ {
+ JsonArgument *json_argument = castNode(JsonArgument, lfirst(lc));
+ deparseJsonValueExpr(state, json_argument->val);
+ deparseAppendStringInfoString(state, " AS ");
+ deparseColLabel(state, json_argument->name);
+
+ if (lnext(json_table->passing, lc))
+ deparseAppendStringInfoString(state, ", ");
+ }
+
+ deparseJsonTableColumns(state, json_table->columns);
+
+ if (json_table->on_error)
+ {
+ deparseJsonBehavior(state, json_table->on_error);
+ deparseAppendStringInfoString(state, " ON ERROR");
+ }
+
+ deparseAppendStringInfoChar(state, ')');
+
+ if (json_table->alias)
+ {
+ deparseAppendStringInfoChar(state, ' ');
+ deparseAlias(state, json_table->alias);
+ }
+}
+
+static void deparseGroupingFunc(DeparseState *state, GroupingFunc *grouping_func)
+{
+ deparseAppendStringInfoString(state, "GROUPING(");
+ deparseExprList(state, grouping_func->args);
+ deparseAppendStringInfoChar(state, ')');
+}
+
+static void deparseClusterStmt(DeparseState *state, ClusterStmt *cluster_stmt)
+{
+ deparseAppendStringInfoString(state, "CLUSTER ");
+
+ deparseUtilityOptionList(state, cluster_stmt->params);
+
+ if (cluster_stmt->relation != NULL)
+ {
+ deparseRangeVar(state, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ if (cluster_stmt->indexname != NULL)
+ {
+ deparseAppendStringInfoString(state, "USING ");
+ deparseAppendStringInfoString(state, quote_identifier(cluster_stmt->indexname));
+ deparseAppendStringInfoChar(state, ' ');
+ }
+
+ removeTrailingSpace(state);
+}
+
+static void deparseValue(DeparseState *state, union ValUnion *value, DeparseNodeContext context)
+{
+ if (!value) {
+ deparseAppendStringInfoString(state, "NULL");
+ return;
+ }
+
+ switch (nodeTag(value))
+ {
+ case T_Integer:
+ case T_Float:
+ deparseNumericOnly(state, value);
+ break;
+ case T_Boolean:
+ deparseAppendStringInfoString(state, value->boolval.boolval ? "true" : "false");
+ break;
+ case T_String:
+ if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
+ deparseAppendStringInfoString(state, quote_identifier(value->sval.sval));
+ } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
+ deparseStringLiteral(state, value->sval.sval);
+ } else {
+ deparseAppendStringInfoString(state, value->sval.sval);
+ }
+ break;
+ case T_BitString:
+ if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'x')
+ {
+ deparseAppendStringInfoChar(state, 'x');
+ deparseStringLiteral(state, value->sval.sval + 1);
+ }
+ else if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'b')
+ {
+ deparseAppendStringInfoChar(state, 'b');
+ deparseStringLiteral(state, value->sval.sval + 1);
+ }
+ else
+ {
+ Assert(false);
+ }
+ break;
+ default:
+ elog(ERROR, "deparse: unrecognized value node type: %d",
+ (int) nodeTag(value));
+ break;
+ }
+}
+
+// "PrepareableStmt" in gram.y
+static void deparsePreparableStmt(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(state, castNode(SelectStmt, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(state, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(state, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(state, castNode(DeleteStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(state, castNode(MergeStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "RuleActionStmt" in gram.y
+static void deparseRuleActionStmt(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(state, castNode(SelectStmt, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(state, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(state, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(state, castNode(DeleteStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(state, castNode(NotifyStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "ExplainableStmt" in gram.y
+static void deparseExplainableStmt(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_SelectStmt:
+ deparseSelectStmt(state, castNode(SelectStmt, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(state, castNode(InsertStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(state, castNode(UpdateStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(state, castNode(DeleteStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(state, castNode(DeclareCursorStmt, node));
+ break;
+ case T_CreateTableAsStmt:
+ deparseCreateTableAsStmt(state, castNode(CreateTableAsStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(state, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(state, castNode(ExecuteStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(state, castNode(MergeStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "schema_stmt" in gram.y
+static void deparseSchemaStmt(DeparseState *state, Node *node)
+{
+ switch (nodeTag(node))
+ {
+ case T_CreateStmt:
+ deparseCreateStmt(state, castNode(CreateStmt, node), false);
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(state, castNode(IndexStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(state, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(state, castNode(CreateTrigStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(state, castNode(GrantStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(state, castNode(ViewStmt, node));
+ break;
+ default:
+ Assert(false);
+ }
+}
+
+// "stmt" in gram.y
+static void deparseStmt(DeparseState *state, Node *node)
+{
+ DeparseStateNestingLevel *parent_level = NULL;
+
+ // For statements that can be nested, push/pop is handled directly in the
+ // respective deparse...Stmt methods
+ bool skip_push_pop = IsA(node, SelectStmt) ||
+ IsA(node, InsertStmt) ||
+ IsA(node, UpdateStmt) ||
+ IsA(node, DeleteStmt) ||
+ IsA(node, MergeStmt);
+
+ if (!skip_push_pop)
+ parent_level = deparseStateIncreaseNestingLevel(state);
+
+ // Note the following grammar names are missing in the list, because they
+ // get mapped to other node types:
+ //
+ // - AlterForeignTableStmt (=> AlterTableStmt)
+ // - AlterGroupStmt (=> AlterRoleStmt)
+ // - AlterCompositeTypeStmt (=> AlterTableStmt)
+ // - AnalyzeStmt (=> VacuumStmt)
+ // - CreateGroupStmt (=> CreateRoleStmt)
+ // - CreateMatViewStmt (=> CreateTableAsStmt)
+ // - CreateUserStmt (=> CreateRoleStmt)
+ // - DropCastStmt (=> DropStmt)
+ // - DropOpClassStmt (=> DropStmt)
+ // - DropOpFamilyStmt (=> DropStmt)
+ // - DropPLangStmt (=> DropPLangStmt)
+ // - DropTransformStmt (=> DropStmt)
+ // - RemoveAggrStmt (=> DropStmt)
+ // - RemoveFuncStmt (=> DropStmt)
+ // - RemoveOperStmt (=> DropStmt)
+ // - RevokeStmt (=> GrantStmt)
+ // - RevokeRoleStmt (=> GrantRoleStmt)
+ // - VariableResetStmt (=> VariableSetStmt)
+ //
+ // And the following grammar names error out in the parser:
+ // - CreateAssertionStmt (not supported yet)
+ switch (nodeTag(node))
+ {
+ case T_AlterEventTrigStmt:
+ deparseAlterEventTrigStmt(state, castNode(AlterEventTrigStmt, node));
+ break;
+ case T_AlterCollationStmt:
+ deparseAlterCollationStmt(state, castNode(AlterCollationStmt, node));
+ break;
+ case T_AlterDatabaseStmt:
+ deparseAlterDatabaseStmt(state, castNode(AlterDatabaseStmt, node));
+ break;
+ case T_AlterDatabaseSetStmt:
+ deparseAlterDatabaseSetStmt(state, castNode(AlterDatabaseSetStmt, node));
+ break;
+ case T_AlterDefaultPrivilegesStmt:
+ deparseAlterDefaultPrivilegesStmt(state, castNode(AlterDefaultPrivilegesStmt, node));
+ break;
+ case T_AlterDomainStmt:
+ deparseAlterDomainStmt(state, castNode(AlterDomainStmt, node));
+ break;
+ case T_AlterEnumStmt:
+ deparseAlterEnumStmt(state, castNode(AlterEnumStmt, node));
+ break;
+ case T_AlterExtensionStmt:
+ deparseAlterExtensionStmt(state, castNode(AlterExtensionStmt, node));
+ break;
+ case T_AlterExtensionContentsStmt:
+ deparseAlterExtensionContentsStmt(state, castNode(AlterExtensionContentsStmt, node));
+ break;
+ case T_AlterFdwStmt:
+ deparseAlterFdwStmt(state, castNode(AlterFdwStmt, node));
+ break;
+ case T_AlterForeignServerStmt:
+ deparseAlterForeignServerStmt(state, castNode(AlterForeignServerStmt, node));
+ break;
+ case T_AlterFunctionStmt:
+ deparseAlterFunctionStmt(state, castNode(AlterFunctionStmt, node));
+ break;
+ case T_AlterObjectDependsStmt:
+ deparseAlterObjectDependsStmt(state, castNode(AlterObjectDependsStmt, node));
+ break;
+ case T_AlterObjectSchemaStmt:
+ deparseAlterObjectSchemaStmt(state, castNode(AlterObjectSchemaStmt, node));
+ break;
+ case T_AlterOwnerStmt:
+ deparseAlterOwnerStmt(state, castNode(AlterOwnerStmt, node));
+ break;
+ case T_AlterOperatorStmt:
+ deparseAlterOperatorStmt(state, castNode(AlterOperatorStmt, node));
+ break;
+ case T_AlterTypeStmt:
+ deparseAlterTypeStmt(state, castNode(AlterTypeStmt, node));
+ break;
+ case T_AlterPolicyStmt:
+ deparseAlterPolicyStmt(state, castNode(AlterPolicyStmt, node));
+ break;
+ case T_AlterSeqStmt:
+ deparseAlterSeqStmt(state, castNode(AlterSeqStmt, node));
+ break;
+ case T_AlterSystemStmt:
+ deparseAlterSystemStmt(state, castNode(AlterSystemStmt, node));
+ break;
+ case T_AlterTableMoveAllStmt:
+ deparseAlterTableMoveAllStmt(state, castNode(AlterTableMoveAllStmt, node));
+ break;
+ case T_AlterTableStmt:
+ deparseAlterTableStmt(state, castNode(AlterTableStmt, node));
+ break;
+ case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
+ deparseAlterTableSpaceOptionsStmt(state, castNode(AlterTableSpaceOptionsStmt, node));
+ break;
+ case T_AlterPublicationStmt:
+ deparseAlterPublicationStmt(state, castNode(AlterPublicationStmt, node));
+ break;
+ case T_AlterRoleSetStmt:
+ deparseAlterRoleSetStmt(state, castNode(AlterRoleSetStmt, node));
+ break;
+ case T_AlterRoleStmt:
+ deparseAlterRoleStmt(state, castNode(AlterRoleStmt, node));
+ break;
+ case T_AlterSubscriptionStmt:
+ deparseAlterSubscriptionStmt(state, castNode(AlterSubscriptionStmt, node));
+ break;
+ case T_AlterStatsStmt:
+ deparseAlterStatsStmt(state, castNode(AlterStatsStmt, node));
+ break;
+ case T_AlterTSConfigurationStmt:
+ deparseAlterTSConfigurationStmt(state, castNode(AlterTSConfigurationStmt, node));
+ break;
+ case T_AlterTSDictionaryStmt:
+ deparseAlterTSDictionaryStmt(state, castNode(AlterTSDictionaryStmt, node));
+ break;
+ case T_AlterUserMappingStmt:
+ deparseAlterUserMappingStmt(state, castNode(AlterUserMappingStmt, node));
+ break;
+ case T_CallStmt:
+ deparseCallStmt(state, castNode(CallStmt, node));
+ break;
+ case T_CheckPointStmt:
+ deparseCheckPointStmt(state, castNode(CheckPointStmt, node));
+ break;
+ case T_ClosePortalStmt:
+ deparseClosePortalStmt(state, castNode(ClosePortalStmt, node));
+ break;
+ case T_ClusterStmt:
+ deparseClusterStmt(state, castNode(ClusterStmt, node));
+ break;
+ case T_CommentStmt:
+ deparseCommentStmt(state, castNode(CommentStmt, node));
+ break;
+ case T_ConstraintsSetStmt:
+ deparseConstraintsSetStmt(state, castNode(ConstraintsSetStmt, node));
+ break;
+ case T_CopyStmt:
+ deparseCopyStmt(state, castNode(CopyStmt, node));
+ break;
+ case T_CreateAmStmt:
+ deparseCreateAmStmt(state, castNode(CreateAmStmt, node));
+ break;
+ case T_CreateTableAsStmt: // "CreateAsStmt" in gram.y
+ deparseCreateTableAsStmt(state, castNode(CreateTableAsStmt, node));
+ break;
+ case T_CreateCastStmt:
+ deparseCreateCastStmt(state, castNode(CreateCastStmt, node));
+ break;
+ case T_CreateConversionStmt:
+ deparseCreateConversionStmt(state, castNode(CreateConversionStmt, node));
+ break;
+ case T_CreateDomainStmt:
+ deparseCreateDomainStmt(state, castNode(CreateDomainStmt, node));
+ break;
+ case T_CreateExtensionStmt:
+ deparseCreateExtensionStmt(state, castNode(CreateExtensionStmt, node));
+ break;
+ case T_CreateFdwStmt:
+ deparseCreateFdwStmt(state, castNode(CreateFdwStmt, node));
+ break;
+ case T_CreateForeignServerStmt:
+ deparseCreateForeignServerStmt(state, castNode(CreateForeignServerStmt, node));
+ break;
+ case T_CreateForeignTableStmt:
+ deparseCreateForeignTableStmt(state, castNode(CreateForeignTableStmt, node));
+ break;
+ case T_CreateFunctionStmt:
+ deparseCreateFunctionStmt(state, castNode(CreateFunctionStmt, node));
+ break;
+ case T_CreateOpClassStmt:
+ deparseCreateOpClassStmt(state, castNode(CreateOpClassStmt, node));
+ break;
+ case T_CreateOpFamilyStmt:
+ deparseCreateOpFamilyStmt(state, castNode(CreateOpFamilyStmt, node));
+ break;
+ case T_CreatePublicationStmt:
+ deparseCreatePublicationStmt(state, castNode(CreatePublicationStmt, node));
+ break;
+ case T_AlterOpFamilyStmt:
+ deparseAlterOpFamilyStmt(state, castNode(AlterOpFamilyStmt, node));
+ break;
+ case T_CreatePolicyStmt:
+ deparseCreatePolicyStmt(state, castNode(CreatePolicyStmt, node));
+ break;
+ case T_CreatePLangStmt:
+ deparseCreatePLangStmt(state, castNode(CreatePLangStmt, node));
+ break;
+ case T_CreateSchemaStmt:
+ deparseCreateSchemaStmt(state, castNode(CreateSchemaStmt, node));
+ break;
+ case T_CreateSeqStmt:
+ deparseCreateSeqStmt(state, castNode(CreateSeqStmt, node));
+ break;
+ case T_CreateStmt:
+ deparseCreateStmt(state, castNode(CreateStmt, node), false);
+ break;
+ case T_CreateSubscriptionStmt:
+ deparseCreateSubscriptionStmt(state, castNode(CreateSubscriptionStmt, node));
+ break;
+ case T_CreateStatsStmt:
+ deparseCreateStatsStmt(state, castNode(CreateStatsStmt, node));
+ break;
+ case T_CreateTableSpaceStmt:
+ deparseCreateTableSpaceStmt(state, castNode(CreateTableSpaceStmt, node));
+ break;
+ case T_CreateTransformStmt:
+ deparseCreateTransformStmt(state, castNode(CreateTransformStmt, node));
+ break;
+ case T_CreateTrigStmt:
+ deparseCreateTrigStmt(state, castNode(CreateTrigStmt, node));
+ break;
+ case T_CreateEventTrigStmt:
+ deparseCreateEventTrigStmt(state, castNode(CreateEventTrigStmt, node));
+ break;
+ case T_CreateRoleStmt:
+ deparseCreateRoleStmt(state, castNode(CreateRoleStmt, node));
+ break;
+ case T_CreateUserMappingStmt:
+ deparseCreateUserMappingStmt(state, castNode(CreateUserMappingStmt, node));
+ break;
+ case T_CreatedbStmt:
+ deparseCreatedbStmt(state, castNode(CreatedbStmt, node));
+ break;
+ case T_DeallocateStmt:
+ deparseDeallocateStmt(state, castNode(DeallocateStmt, node));
+ break;
+ case T_DeclareCursorStmt:
+ deparseDeclareCursorStmt(state, castNode(DeclareCursorStmt, node));
+ break;
+ case T_DefineStmt:
+ deparseDefineStmt(state, castNode(DefineStmt, node));
+ break;
+ case T_DeleteStmt:
+ deparseDeleteStmt(state, castNode(DeleteStmt, node));
+ break;
+ case T_DiscardStmt:
+ deparseDiscardStmt(state, castNode(DiscardStmt, node));
+ break;
+ case T_DoStmt:
+ deparseDoStmt(state, castNode(DoStmt, node));
+ break;
+ case T_DropOwnedStmt:
+ deparseDropOwnedStmt(state, castNode(DropOwnedStmt, node));
+ break;
+ case T_DropStmt:
+ deparseDropStmt(state, castNode(DropStmt, node));
+ break;
+ case T_DropSubscriptionStmt:
+ deparseDropSubscriptionStmt(state, castNode(DropSubscriptionStmt, node));
+ break;
+ case T_DropTableSpaceStmt:
+ deparseDropTableSpaceStmt(state, castNode(DropTableSpaceStmt, node));
+ break;
+ case T_DropRoleStmt:
+ deparseDropRoleStmt(state, castNode(DropRoleStmt, node));
+ break;
+ case T_DropUserMappingStmt:
+ deparseDropUserMappingStmt(state, castNode(DropUserMappingStmt, node));
+ break;
+ case T_DropdbStmt:
+ deparseDropdbStmt(state, castNode(DropdbStmt, node));
+ break;
+ case T_ExecuteStmt:
+ deparseExecuteStmt(state, castNode(ExecuteStmt, node));
+ break;
+ case T_ExplainStmt:
+ deparseExplainStmt(state, castNode(ExplainStmt, node));
+ break;
+ case T_FetchStmt:
+ deparseFetchStmt(state, castNode(FetchStmt, node));
+ break;
+ case T_GrantStmt:
+ deparseGrantStmt(state, castNode(GrantStmt, node));
+ break;
+ case T_GrantRoleStmt:
+ deparseGrantRoleStmt(state, castNode(GrantRoleStmt, node));
+ break;
+ case T_ImportForeignSchemaStmt:
+ deparseImportForeignSchemaStmt(state, castNode(ImportForeignSchemaStmt, node));
+ break;
+ case T_IndexStmt:
+ deparseIndexStmt(state, castNode(IndexStmt, node));
+ break;
+ case T_InsertStmt:
+ deparseInsertStmt(state, castNode(InsertStmt, node));
+ break;
+ case T_ListenStmt:
+ deparseListenStmt(state, castNode(ListenStmt, node));
+ break;
+ case T_RefreshMatViewStmt:
+ deparseRefreshMatViewStmt(state, castNode(RefreshMatViewStmt, node));
+ break;
+ case T_LoadStmt:
+ deparseLoadStmt(state, castNode(LoadStmt, node));
+ break;
+ case T_LockStmt:
+ deparseLockStmt(state, castNode(LockStmt, node));
+ break;
+ case T_MergeStmt:
+ deparseMergeStmt(state, castNode(MergeStmt, node));
+ break;
+ case T_NotifyStmt:
+ deparseNotifyStmt(state, castNode(NotifyStmt, node));
+ break;
+ case T_PrepareStmt:
+ deparsePrepareStmt(state, castNode(PrepareStmt, node));
+ break;
+ case T_ReassignOwnedStmt:
+ deparseReassignOwnedStmt(state, castNode(ReassignOwnedStmt, node));
+ break;
+ case T_ReindexStmt:
+ deparseReindexStmt(state, castNode(ReindexStmt, node));
+ break;
+ case T_RenameStmt:
+ deparseRenameStmt(state, castNode(RenameStmt, node));
+ break;
+ case T_RuleStmt:
+ deparseRuleStmt(state, castNode(RuleStmt, node));
+ break;
+ case T_SecLabelStmt:
+ deparseSecLabelStmt(state, castNode(SecLabelStmt, node));
+ break;
+ case T_SelectStmt:
+ deparseSelectStmt(state, castNode(SelectStmt, node), DEPARSE_NODE_CONTEXT_NONE);
+ break;
+ case T_TransactionStmt:
+ deparseTransactionStmt(state, castNode(TransactionStmt, node));
+ break;
+ case T_TruncateStmt:
+ deparseTruncateStmt(state, castNode(TruncateStmt, node));
+ break;
+ case T_UnlistenStmt:
+ deparseUnlistenStmt(state, castNode(UnlistenStmt, node));
+ break;
+ case T_UpdateStmt:
+ deparseUpdateStmt(state, castNode(UpdateStmt, node));
+ break;
+ case T_VacuumStmt:
+ deparseVacuumStmt(state, castNode(VacuumStmt, node));
+ break;
+ case T_VariableSetStmt:
+ deparseVariableSetStmt(state, castNode(VariableSetStmt, node));
+ break;
+ case T_VariableShowStmt:
+ deparseVariableShowStmt(state, castNode(VariableShowStmt, node));
+ break;
+ case T_ViewStmt:
+ deparseViewStmt(state, castNode(ViewStmt, node));
+ break;
+ // These node types are created by DefineStmt grammar for CREATE TYPE in some cases
+ case T_CompositeTypeStmt:
+ deparseCompositeTypeStmt(state, castNode(CompositeTypeStmt, node));
+ break;
+ case T_CreateEnumStmt:
+ deparseCreateEnumStmt(state, castNode(CreateEnumStmt, node));
+ break;
+ case T_CreateRangeStmt:
+ deparseCreateRangeStmt(state, castNode(CreateRangeStmt, node));
+ break;
+ default:
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
+ }
+
+ if (!skip_push_pop)
+ deparseStateDecreaseNestingLevel(state, parent_level);
+}
+#endif
diff --git a/postgres_deparse.h b/postgres_deparse.h
new file mode 100644
index 0000000..e69c696
--- /dev/null
+++ b/postgres_deparse.h
@@ -0,0 +1,70 @@
+// From https://github.com/pganalyze/libpg_query/tree/156705b347d347c154fdfddf9341c07a9fa73dc2
+
+// Copyright (c) 2015, Lukas Fittl
+// Copyright (c) 2016-2023, Duboce Labs, Inc. (pganalyze)
+// All rights reserved.
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+
+// * Neither the name of pg_query nor the names of its contributors may be used
+// to endorse or promote products derived from this software without specific
+// prior written permission.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef POSTGRES_DEPARSE_H
+#define POSTGRES_DEPARSE_H
+
+#include
+#include
+
+typedef struct PostgresDeparseComment {
+ int match_location; // Insert comment before a node, once we find a node whose location field is equal-or-higher than this location
+ int newlines_before_comment; // Insert newlines before inserting the comment (set to non-zero if the source comment was separated from the prior token by at least one newline)
+ int newlines_after_comment; // Insert newlines after inserting the comment (set to non-zero if the source comment was separated from the next token by at least one newline)
+ char *str; // The actual comment string, including comment start/end tokens, and newline characters in comment (if any)
+} PostgresDeparseComment;
+
+typedef struct PostgresDeparseOpts {
+ PostgresDeparseComment **comments;
+ size_t comment_count;
+
+ // Pretty print options
+ bool pretty_print;
+ int indent_size; // Indentation size (Default 4 spaces)
+ int max_line_length; // Restricts the line length of certain lists of items (Default 80 characters)
+ bool trailing_newline; // Whether to add a trailing newline at the end of the output (Default off)
+ bool commas_start_of_line; // Place separating commas at start of line (Default off)
+} PostgresDeparseOpts;
+
+/* Forward declarations to allow referencing the structs in this include file without needing Postgres includes */
+struct StringInfoData;
+typedef struct StringInfoData *StringInfo;
+struct RawStmt;
+
+extern void deparseRawStmt(StringInfo str, struct RawStmt *raw_stmt);
+#if (PG_MAJORVERSION_NUM >= 18)
+extern void deparseRawStmtOpts(StringInfo str, struct RawStmt *raw_stmt, PostgresDeparseOpts *opts);
+#elif (PG_MAJORVERSION_NUM >= 17)
+extern void deparseRawStmtOpts(StringInfo str, struct RawStmt *raw_stmt, PostgresDeparseOpts opts);
+#endif
+
+#endif
\ No newline at end of file
diff --git a/schema/2.4.sql b/schema/2.4.sql
new file mode 100644
index 0000000..8f2ca45
--- /dev/null
+++ b/schema/2.4.sql
@@ -0,0 +1 @@
+ALTER TABLE pgl_ddl_deploy.set_configs ADD COLUMN include_indexes BOOLEAN NOT NULL DEFAULT FALSE;
diff --git a/sql/56_1_6_features.sql b/sql/56_1_6_features.sql
index 9672768..77ac9a3 100644
--- a/sql/56_1_6_features.sql
+++ b/sql/56_1_6_features.sql
@@ -40,15 +40,3 @@ In <= 1.5, returned this:
{"DROP SCHEMA","DROP TABLE","DROP FUNCTION","DROP TYPE","DROP VIEW","DROP SEQUENCE"}
(1 row)
*/
-
-SET client_min_messages TO warning;
-DROP OWNED BY test_pgl_ddl_deploy;
-DROP ROLE test_pgl_ddl_deploy;
-DROP ROLE unpriv;
-DROP EXTENSION pgl_ddl_deploy CASCADE;
-DROP EXTENSION IF EXISTS pglogical CASCADE;
-DROP SCHEMA IF EXISTS pglogical CASCADE;
-DROP TABLE IF EXISTS tmp_objs;
-DROP SCHEMA IF EXISTS special CASCADE;
-DROP SCHEMA IF EXISTS bla CASCADE;
-DROP SCHEMA IF EXISTS pgl_ddl_deploy CASCADE;
diff --git a/sql/57_2_4_features.sql b/sql/57_2_4_features.sql
new file mode 100644
index 0000000..ec25d6d
--- /dev/null
+++ b/sql/57_2_4_features.sql
@@ -0,0 +1,43 @@
+SET client_min_messages = warning;
+
+CREATE PUBLICATION test_indexes_yes;
+CREATE PUBLICATION test_indexes_no;
+
+INSERT INTO pgl_ddl_deploy.set_configs (set_name, include_schema_regex, lock_safe_deployment, allow_multi_statements, include_indexes)
+VALUES ('test_indexes_yes', '^yindex.*', true, true, true);
+
+INSERT INTO pgl_ddl_deploy.set_configs (set_name, include_schema_regex, lock_safe_deployment, allow_multi_statements, include_indexes)
+VALUES ('test_indexes_no', '^nindex.*', true, true, false);
+
+SELECT pgl_ddl_deploy.deploy('test_indexes_yes');
+SELECT pgl_ddl_deploy.deploy('test_indexes_no');
+
+CREATE SCHEMA yindex;
+CREATE TABLE yindex.widgets(id serial primary key, type varchar);
+CREATE SCHEMA nindex;
+CREATE TABLE nindex.widgets(id serial primary key, type varchar);
+
+CREATE INDEX yindex_widgets_type_idx ON yindex.widgets(type);
+CREATE INDEX CONCURRENTLY nindex_widgets_type_id_idx ON yindex.widgets(type, id);
+CREATE INDEX nindex_widgets_type_idx ON nindex.widgets(type);
+
+DROP TABLE yindex.widgets CASCADE;
+DROP TABLE nindex.widgets CASCADE;
+
+-- We expect to see index events for yindex.widgets but not for nindex.widgets
+SELECT c.set_name, ddl_sql_raw, ddl_sql_sent, c.ddl_only_replication
+FROM pgl_ddl_deploy.events e
+INNER JOIN pgl_ddl_deploy.set_configs c ON c.id = e.set_config_id
+ORDER BY e.id DESC LIMIT 10;
+
+SET client_min_messages TO warning;
+DROP OWNED BY test_pgl_ddl_deploy;
+DROP ROLE test_pgl_ddl_deploy;
+DROP ROLE unpriv;
+DROP EXTENSION pgl_ddl_deploy CASCADE;
+DROP EXTENSION IF EXISTS pglogical CASCADE;
+DROP SCHEMA IF EXISTS pglogical CASCADE;
+DROP TABLE IF EXISTS tmp_objs;
+DROP SCHEMA IF EXISTS special CASCADE;
+DROP SCHEMA IF EXISTS bla CASCADE;
+DROP SCHEMA IF EXISTS pgl_ddl_deploy CASCADE;
diff --git a/sql/57_native_features.sql b/sql/99_native_features.sql
similarity index 100%
rename from sql/57_native_features.sql
rename to sql/99_native_features.sql
diff --git a/test_all_versions.sh b/test_all_versions.sh
index 3797a0e..7ed318d 100755
--- a/test_all_versions.sh
+++ b/test_all_versions.sh
@@ -44,5 +44,5 @@ make_and_test "16" $from_version
make_and_test "17" $from_version
make_and_test "18" $from_version
}
+test_all_versions "2.4"
test_all_versions "2.3"
-test_all_versions "2.2"
diff --git a/views/event_trigger_schema.sql b/views/event_trigger_schema.sql
index cfebb3e..76a2223 100644
--- a/views/event_trigger_schema.sql
+++ b/views/event_trigger_schema.sql
@@ -41,7 +41,6 @@ WITH vars AS
We need to strip the DDL of:
1. Transaction begin and commit, which cannot run inside plpgsql
*****/
- v_ddl_strip_regex TEXT = '(begin\W*transaction\W*|begin\W*work\W*|begin\W*|commit\W*transaction\W*|commit\W*work\W*|commit\W*);';
v_txid BIGINT;
v_ddl_length INT;
v_sql TEXT;
@@ -193,15 +192,7 @@ WITH vars AS
END LOOP;
END IF;
- v_ddl_sql_sent = v_ddl_sql_raw;
-
- --If there are BEGIN/COMMIT tags, attempt to strip and reparse
- IF (SELECT ARRAY['BEGIN','COMMIT']::TEXT[] && v_sql_tags) THEN
- v_ddl_sql_sent = regexp_replace(v_ddl_sql_sent, v_ddl_strip_regex, '', 'ig');
-
- --Sanity reparse
- PERFORM pgl_ddl_deploy.sql_command_tags(v_ddl_sql_sent);
- END IF;
+ SELECT pgl_ddl_deploy.rewrite_transaction_safe(v_ddl_sql_raw) INTO v_ddl_sql_sent;
--Get provider name, in order only to run command on a subscriber to this provider
c_provider_name:=pgl_ddl_deploy.provider_node_name(c_driver);
@@ -285,7 +276,8 @@ WITH vars AS
$BUILD$::TEXT AS shared_mixed_obj_logic,
$BUILD$
-- Filter out purely PG-internal triggers (alas, "pg_event_trigger_dropped_objects" does not expose "tgisinternal", so we must filter by name)
- (SELECT * FROM pg_event_trigger_dropped_objects() WHERE address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_a_%' AND address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_c_%')
+ -- Also filter out toast tables since if there are any non-toast operations the toast ones are almost certainly internally generated
+ (SELECT * FROM pg_event_trigger_dropped_objects() WHERE address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_a_%' AND address_names[array_upper(address_names, 1)] NOT LIKE 'RI_ConstraintTrigger_c_%' AND schema_name <> 'pg_toast')
$BUILD$::TEXT AS dropped_objects_query,
$BUILD$