diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 2901b0ff203186b5e1f4b36aff9c675ca999b7e1..19d4ff9b68138424a5299b9d6d6ab17d8699bac4 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -61,6 +61,7 @@ #include "utils/memutils.h" #include "utils/relmapper.h" +#include "utils/builtins.h" #include "utils/resource_manager.h" #include "utils/sharedsnapshot.h" #include "access/clog.h" @@ -4578,7 +4579,7 @@ DefineDispatchSavepoint(char *name) { char *cmd; - cmd = psprintf("SAVEPOINT %s", name); + cmd = psprintf("SAVEPOINT %s", quote_identifier(name)); /* * dispatch a DTX command, in the event of an error, this call @@ -4711,7 +4712,7 @@ ReleaseSavepoint(List *options) { char *cmd; - cmd = psprintf("RELEASE SAVEPOINT %s", name); + cmd = psprintf("RELEASE SAVEPOINT %s", quote_identifier(name)); /* * dispatch a DTX command, in the event of an error, this call will @@ -4878,7 +4879,7 @@ DispatchRollbackToSavepoint(char *name) if (!name) elog(ERROR, "could not find savepoint name for ROLLBACK TO SAVEPOINT"); - cmd = psprintf("ROLLBACK TO SAVEPOINT %s", name); + cmd = psprintf("ROLLBACK TO SAVEPOINT %s", quote_identifier(name)); /* * dispatch a DTX command, in the event of an error, this call will diff --git a/src/test/regress/expected/gpdtm_plpgsql.out b/src/test/regress/expected/gpdtm_plpgsql.out index 2e2aa1294d9bef038a939080575103304887839b..84cec361a3c231d2820249d6c714f03e8700363f 100644 --- a/src/test/regress/expected/gpdtm_plpgsql.out +++ b/src/test/regress/expected/gpdtm_plpgsql.out @@ -1013,3 +1013,28 @@ $$ language plpgsql; create table stran_tt as select stran_func(b) from stran_foo; NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'stran_func' as the Greenplum Database data distribution key for this table. HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +-- +-- Check quoting when dispatching savepoints. (Not really PL/pgSQL related, +-- but here for lack of a better place.) +-- +BEGIN; +CREATE TEMPORARY TABLE savepointtest (t text); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 't' as the Greenplum Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +INSERT INTO savepointtest VALUES ('before savepoints'); +SAVEPOINT "evil""savepoint1"; +INSERT INTO savepointtest VALUES ('after sp 1'); +SAVEPOINT "evil""savepoint2"; +INSERT INTO savepointtest VALUES ('after sp 2'); +ROLLBACK TO SAVEPOINT "evil""savepoint2"; +RELEASE SAVEPOINT "evil""savepoint1"; +INSERT INTO savepointtest VALUES ('back to top transaction'); +COMMIT; +SELECT * FROM savepointtest; + t +------------------------- + before savepoints + after sp 1 + back to top transaction +(3 rows) + diff --git a/src/test/regress/sql/gpdtm_plpgsql.sql b/src/test/regress/sql/gpdtm_plpgsql.sql index 0b504fbbf183b75871315aeb4b35d7f057c90b99..e7bd10cb7930b8ac34bdead512c949a7bc1d9aaf 100644 --- a/src/test/regress/sql/gpdtm_plpgsql.sql +++ b/src/test/regress/sql/gpdtm_plpgsql.sql @@ -372,3 +372,21 @@ end; $$ language plpgsql; create table stran_tt as select stran_func(b) from stran_foo; + + +-- +-- Check quoting when dispatching savepoints. (Not really PL/pgSQL related, +-- but here for lack of a better place.) +-- +BEGIN; +CREATE TEMPORARY TABLE savepointtest (t text); +INSERT INTO savepointtest VALUES ('before savepoints'); +SAVEPOINT "evil""savepoint1"; +INSERT INTO savepointtest VALUES ('after sp 1'); +SAVEPOINT "evil""savepoint2"; +INSERT INTO savepointtest VALUES ('after sp 2'); +ROLLBACK TO SAVEPOINT "evil""savepoint2"; +RELEASE SAVEPOINT "evil""savepoint1"; +INSERT INTO savepointtest VALUES ('back to top transaction'); +COMMIT; +SELECT * FROM savepointtest;