aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-05-30 14:05:20 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-05-30 14:05:20 -0400
commit5f0adec2537dab531ef63ff6e0fe640698a291d9 (patch)
tree55e8405a62f603d2f9ae37b80e2493c909f30654 /src
parenta8cca6026e992d9b627c7dbee5f8a50bde507a94 (diff)
downloadpostgresql-5f0adec2537dab531ef63ff6e0fe640698a291d9.tar.gz
postgresql-5f0adec2537dab531ef63ff6e0fe640698a291d9.zip
Make STRING an unreserved_keyword.
Commit 1a36bc9db (SQL/JSON query functions) introduced STRING as a type_func_name_keyword, thereby breaking applications that use "string" as a table name, column name, function parameter name, etc. That seems like a pretty bad thing, not least because the SQL spec says that STRING is an unreserved keyword. This is easy enough to fix so far as the core grammar is concerned. However, doing so causes some ECPG test cases to fail, specifically those that use "string" as a typedef name. It turns out this is because portions of the ECPG grammar allow type_func_name_keywords but not unreserved_keywords as typedef names. That's pretty horrid, and it's mildly astonishing that we've not heard complaints about it before. We can fix two of those uses trivially, but the ones in the var_type production are less easy. As a stopgap, hard-code STRING as an allowed alternative in var_type. Per report from Alastair McKinley. Discussion: https://postgr.es/m/3661437.1653855582@sss.pgh.pa.us
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/gram.y2
-rw-r--r--src/include/parser/kwlist.h2
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.trailer41
3 files changed, 41 insertions, 4 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 989db0dbece..969c9c158f6 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -17940,6 +17940,7 @@ unreserved_keyword:
| STORAGE
| STORED
| STRICT_P
+ | STRING
| STRIP_P
| SUBSCRIPTION
| SUPPORT
@@ -18098,7 +18099,6 @@ type_func_name_keyword:
| OVERLAPS
| RIGHT
| SIMILAR
- | STRING
| TABLESAMPLE
| VERBOSE
;
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 8a2ab405a28..ae35f032513 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -426,7 +426,7 @@ PG_KEYWORD("stdout", STDOUT, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("storage", STORAGE, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("stored", STORED, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("strict", STRICT_P, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("string", STRING, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("string", STRING, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("strip", STRIP_P, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("subscription", SUBSCRIPTION, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("substring", SUBSTRING, COL_NAME_KEYWORD, BARE_LABEL)
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
index daf979a8e82..b95fc44314d 100644
--- a/src/interfaces/ecpg/preproc/ecpg.trailer
+++ b/src/interfaces/ecpg/preproc/ecpg.trailer
@@ -467,7 +467,7 @@ type_declaration: S_TYPEDEF
/* an initializer specified */
initializer = 0;
}
- var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
+ var_type opt_pointer ECPGColLabel opt_array_bounds ';'
{
add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0);
@@ -701,6 +701,43 @@ var_type: simple_type
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
}
}
+ | STRING
+ {
+ /*
+ * It's quite horrid that ECPGColLabelCommon excludes
+ * unreserved_keyword, meaning that unreserved keywords can't be
+ * used as type names in var_type. However, this is hard to avoid
+ * since what follows ecpgstart can be either a random SQL
+ * statement or an ECPGVarDeclaration (beginning with var_type).
+ * Pending a bright idea about how to fix that, we must
+ * special-case STRING (and any other unreserved keywords that are
+ * likely to be needed here).
+ */
+ if (INFORMIX_MODE)
+ {
+ $$.type_enum = ECPGt_string;
+ $$.type_str = mm_strdup("char");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ else
+ {
+ /* this is for typedef'ed types */
+ struct typedefs *this = get_typedef("string");
+
+ $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name);
+ $$.type_enum = this->type->type_enum;
+ $$.type_dimension = this->type->type_dimension;
+ $$.type_index = this->type->type_index;
+ if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
+ $$.type_sizeof = this->type->type_sizeof;
+ else
+ $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")"));
+
+ struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+ }
+ }
| s_struct_union_symbol
{
/* this is for named structs/unions */
@@ -1342,7 +1379,7 @@ ECPGTypedef: TYPE_P
/* an initializer specified */
initializer = 0;
}
- ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
+ ECPGColLabel IS var_type opt_array_bounds opt_reference
{
add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0);