diff options
author | Pavan Deolasee | 2017-01-05 14:04:36 +0000 |
---|---|---|
committer | Pavan Deolasee | 2017-05-05 04:59:33 +0000 |
commit | 1e1f85b67f577cd86b4aa0b5387dfaba7272a28e (patch) | |
tree | 551a6262bea9eecb056ba0ac71e2331fcbd80890 | |
parent | cad751b23b2ed7a2371b3bb9074cd93d38c7bfb7 (diff) |
Ensure variable values are quoted when necessary while sending down SET
comamnds to the remote nodes
Earlier we'd special cased a few GUCs such as those using memory or time units
or transaction isolation levels. But clearly that wasn't enough as we noticed
with "application_name" recently. So fix this problem in a more comprehensive
manner.
Added a few more test cases to cover these scenarios.
-rw-r--r-- | src/backend/pgxc/pool/execRemote.c | 2 | ||||
-rw-r--r-- | src/backend/pgxc/pool/pgxcnode.c | 25 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 59 | ||||
-rw-r--r-- | src/include/pgxc/pgxcnode.h | 3 | ||||
-rw-r--r-- | src/include/utils/guc.h | 1 | ||||
-rw-r--r-- | src/test/regress/sql/guc.sql | 96 |
6 files changed, 139 insertions, 47 deletions
diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index 321fa1fee2..d6e842301e 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -1912,7 +1912,7 @@ pgxc_node_begin(int conn_count, PGXCNodeHandle **connections, /* Send virtualXID to the remote nodes using SET command */ sprintf(lxid, "%d", MyProc->lxid); - PGXCNodeSetParam(true, "coordinator_lxid", lxid); + PGXCNodeSetParam(true, "coordinator_lxid", lxid, 0); /* after transactions are started send down local set commands */ init_str = PGXCNodeGetTransactionParamStr(); diff --git a/src/backend/pgxc/pool/pgxcnode.c b/src/backend/pgxc/pool/pgxcnode.c index 28a5bbb4c6..4375e8813a 100644 --- a/src/backend/pgxc/pool/pgxcnode.c +++ b/src/backend/pgxc/pool/pgxcnode.c @@ -107,6 +107,7 @@ typedef struct { NameData name; NameData value; + int flags; } ParamEntry; @@ -2568,7 +2569,7 @@ paramlist_delete_param(List *param_list, const char *name) * values on newly connected remote nodes. */ void -PGXCNodeSetParam(bool local, const char *name, const char *value) +PGXCNodeSetParam(bool local, const char *name, const char *value, int flags) { List *param_list; MemoryContext oldcontext; @@ -2596,6 +2597,7 @@ PGXCNodeSetParam(bool local, const char *name, const char *value) entry = (ParamEntry *) palloc(sizeof (ParamEntry)); strlcpy((char *) (&entry->name), name, NAMEDATALEN); strlcpy((char *) (&entry->value), value, NAMEDATALEN); + entry->flags = flags; param_list = lappend(param_list, entry); } @@ -2647,25 +2649,6 @@ PGXCNodeResetParams(bool only_local) local_params = NULL; } - -#ifdef NOT_USED -static char * -quote_ident_cstr(char *rawstr) -{ - text *rawstr_text; - text *result_text; - char *result; - - rawstr_text = cstring_to_text(rawstr); - result_text = DatumGetTextP(DirectFunctionCall1(quote_ident, - PointerGetDatum(rawstr_text))); - result = text_to_cstring(result_text); - - return result; -} -#endif - - static void get_set_command(List *param_list, StringInfo command, bool local) { @@ -2682,6 +2665,8 @@ get_set_command(List *param_list, StringInfo command, bool local) if (strlen(value) == 0) value = "''"; + value = quote_guc_value(value, entry->flags); + appendStringInfo(command, "SET %s %s TO %s;", local ? "LOCAL" : "", NameStr(entry->name), value); } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index eaeaadb9cd..ff26c2e2c7 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5650,13 +5650,9 @@ AtEOXact_GUC(bool isCommit, int nestLevel) /* XXX perhaps this should use is_missing=false, not sure */ newvalStr = GetConfigOptionByName(gconf->name, NULL, true); - /* - * Quote value if it is including memory or time units - */ - if (newvalStr && (gconf->flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME))) - newvalStr = quote_identifier(newvalStr); if (newvalStr) - PGXCNodeSetParam((stack->state == GUC_LOCAL), gconf->name, newvalStr); + PGXCNodeSetParam((stack->state == GUC_LOCAL), gconf->name, + newvalStr, gconf->flags); } /* Finish popping the state stack */ @@ -6981,38 +6977,24 @@ set_config_option(const char *name, const char *value, initStringInfo(&poolcmd); /* - * We are getting parse error when sending down - * SET transaction_isolation TO read committed; - * XXX generic solution? - */ - if (value && strcmp("transaction_isolation", name) == 0) - value = quote_identifier(value); - - if (value && strcmp("default_transaction_isolation", name) == 0) - value = quote_identifier(value); - - /* - * Quote value if it is including memory or time units - */ - if (value && (record->flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME))) - value = quote_identifier(value); - - /* * Save new parameter value with the node manager. * XXX here we may check: if value equals to configuration default * just reset parameter instead. Minus one table entry, shorter SET * command sent downn... Sounds like optimization. */ + if (action == GUC_ACTION_LOCAL) { if (IsTransactionBlock()) - PGXCNodeSetParam(true, name, value); + PGXCNodeSetParam(true, name, value, record->flags); + value = quote_guc_value(value, record->flags); appendStringInfo(&poolcmd, "SET LOCAL %s TO %s", name, (value ? value : "DEFAULT")); } else { - PGXCNodeSetParam(false, name, value); + PGXCNodeSetParam(false, name, value, record->flags); + value = quote_guc_value(value, record->flags); appendStringInfo(&poolcmd, "SET %s TO %s", name, (value ? value : "DEFAULT")); } @@ -10940,4 +10922,31 @@ check_storm_catalog_remap_string(char **newval, void **extra, GucSource source) return true; } #endif + +#ifdef XCP +/* + * Return a quoted GUC value, when necessary + */ +char * +quote_guc_value(const char *value, int flags) +{ + if (value == NULL) + return value; + + /* + * If the GUC rceives list input, then the individual elements in the list + * must be already quoted correctly by flatten_set_variable_args(). We must + * not quote the entire value again + */ + if (flags & GUC_LIST_INPUT) + return value; + + /* + * Otherwise quote the value. quote_identifier() takes care of correctly + * quoting the value when needed, including GUC_UNIT_MEMORY and + * GUC_UNIT_TIME values. + */ + return quote_identifier(value); +} +#endif #include "guc-file.c" diff --git a/src/include/pgxc/pgxcnode.h b/src/include/pgxc/pgxcnode.h index f40120671f..7ad15c7c6a 100644 --- a/src/include/pgxc/pgxcnode.h +++ b/src/include/pgxc/pgxcnode.h @@ -187,7 +187,8 @@ extern void add_error_message(PGXCNodeHandle * handle, const char *message); extern Datum pgxc_execute_on_nodes(int numnodes, Oid *nodelist, char *query); -extern void PGXCNodeSetParam(bool local, const char *name, const char *value); +extern void PGXCNodeSetParam(bool local, const char *name, const char *value, + int flags); extern void PGXCNodeResetParams(bool only_local); extern char *PGXCNodeGetSessionParamStr(void); extern char *PGXCNodeGetTransactionParamStr(void); diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index a831fa2777..9fb76be629 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -446,5 +446,6 @@ extern void assign_search_path(const char *newval, void *extra); /* in access/transam/xlog.c */ extern bool check_wal_buffers(int *newval, void **extra, GucSource source); extern void assign_xlog_sync_method(int new_sync_method, void *extra); +extern char *quote_guc_value(const char *value, int flags); #endif /* GUC_H */ diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql index 95ac9cb43b..60133f1891 100644 --- a/src/test/regress/sql/guc.sql +++ b/src/test/regress/sql/guc.sql @@ -209,3 +209,99 @@ set default_text_search_config = no_such_config; select func_with_bad_set(); reset check_function_bodies; + +SET application_name TO "special name"; +CREATE TABLE testtab (a int); +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +SET default_transaction_isolation TO "read committed"; +CREATE TABLE testtab (a int); +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +SET work_mem TO '64kB'; +CREATE TABLE testtab (a int); +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +SET work_mem TO "64kB"; +CREATE TABLE testtab (a int); +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +SET log_min_duration_statement = '1s'; +CREATE TABLE testtab (a int); +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +CREATE SCHEMA testschema; +CREATE SCHEMA "testschema 2"; +CREATE SCHEMA "testschema 3"; +CREATE SCHEMA READ; +CREATE SCHEMA "READ"; + +-- ERROR +CREATE SCHEMA SELECT; + +-- Ok +CREATE SCHEMA "SELECT"; + +SET search_path TO testschema; +CREATE TABLE testtab (a int); +\d+ testtab +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +SET search_path TO "testschema"; +CREATE TABLE testtab (a int); +\d+ testtab +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +SET search_path TO testschema, "testschema 2"; +CREATE TABLE testtab (a int); +\d+ testtab +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +SET search_path TO "testschema 3", "testschema 2"; +CREATE TABLE testtab (a int); +\d+ testtab +INSERT INTO testtab VALUES (1), (2), (3); +SELECT * FROM testtab; +DROP TABLE testtab; + +-- ERROR +SET search_path TO "testschema 3", SELECT; + +SET search_path TO "SELECT", "testschema 3"; +CREATE TABLE testtab (a int); +\d+ testtab +CREATE TABLE "testschema 3".testtab (a int); +\d+ testtab +INSERT INTO "testschema 3".testtab VALUES (1), (2), (3); +INSERT INTO "SELECT".testtab VALUES (4); +SELECT * FROM "testschema 3".testtab; +INSERT INTO testtab SELECT * FROM "testschema 3".testtab; +SELECT * FROM "testschema 3".testtab; +\d+ testtab +SELECT * FROM testtab; +INSERT INTO testtab SELECT * FROM testtab; +SELECT * FROM testtab; +DROP TABLE testtab; + +DROP SCHEMA testschema CASCADE; +DROP SCHEMA "testschema 2" CASCADE; +DROP SCHEMA "testschema 3" CASCADE; +DROP SCHEMA "READ" CASCADE; +DROP SCHEMA SELECT CASCADE; +DROP SCHEMA "SELECT" CASCADE; |