Skip to content

Commit 5f0adec

Browse files
committed
Make STRING an unreserved_keyword.
Commit 1a36bc9 (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
1 parent a8cca60 commit 5f0adec

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

src/backend/parser/gram.y

+1-1
Original file line numberDiff line numberDiff line change
@@ -17940,6 +17940,7 @@ unreserved_keyword:
1794017940
| STORAGE
1794117941
| STORED
1794217942
| STRICT_P
17943+
| STRING
1794317944
| STRIP_P
1794417945
| SUBSCRIPTION
1794517946
| SUPPORT
@@ -18098,7 +18099,6 @@ type_func_name_keyword:
1809818099
| OVERLAPS
1809918100
| RIGHT
1810018101
| SIMILAR
18101-
| STRING
1810218102
| TABLESAMPLE
1810318103
| VERBOSE
1810418104
;

src/include/parser/kwlist.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ PG_KEYWORD("stdout", STDOUT, UNRESERVED_KEYWORD, BARE_LABEL)
426426
PG_KEYWORD("storage", STORAGE, UNRESERVED_KEYWORD, BARE_LABEL)
427427
PG_KEYWORD("stored", STORED, UNRESERVED_KEYWORD, BARE_LABEL)
428428
PG_KEYWORD("strict", STRICT_P, UNRESERVED_KEYWORD, BARE_LABEL)
429-
PG_KEYWORD("string", STRING, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
429+
PG_KEYWORD("string", STRING, UNRESERVED_KEYWORD, BARE_LABEL)
430430
PG_KEYWORD("strip", STRIP_P, UNRESERVED_KEYWORD, BARE_LABEL)
431431
PG_KEYWORD("subscription", SUBSCRIPTION, UNRESERVED_KEYWORD, BARE_LABEL)
432432
PG_KEYWORD("substring", SUBSTRING, COL_NAME_KEYWORD, BARE_LABEL)

src/interfaces/ecpg/preproc/ecpg.trailer

+39-2
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ type_declaration: S_TYPEDEF
467467
/* an initializer specified */
468468
initializer = 0;
469469
}
470-
var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
470+
var_type opt_pointer ECPGColLabel opt_array_bounds ';'
471471
{
472472
add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0);
473473

@@ -701,6 +701,43 @@ var_type: simple_type
701701
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
702702
}
703703
}
704+
| STRING
705+
{
706+
/*
707+
* It's quite horrid that ECPGColLabelCommon excludes
708+
* unreserved_keyword, meaning that unreserved keywords can't be
709+
* used as type names in var_type. However, this is hard to avoid
710+
* since what follows ecpgstart can be either a random SQL
711+
* statement or an ECPGVarDeclaration (beginning with var_type).
712+
* Pending a bright idea about how to fix that, we must
713+
* special-case STRING (and any other unreserved keywords that are
714+
* likely to be needed here).
715+
*/
716+
if (INFORMIX_MODE)
717+
{
718+
$$.type_enum = ECPGt_string;
719+
$$.type_str = mm_strdup("char");
720+
$$.type_dimension = mm_strdup("-1");
721+
$$.type_index = mm_strdup("-1");
722+
$$.type_sizeof = NULL;
723+
}
724+
else
725+
{
726+
/* this is for typedef'ed types */
727+
struct typedefs *this = get_typedef("string");
728+
729+
$$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name);
730+
$$.type_enum = this->type->type_enum;
731+
$$.type_dimension = this->type->type_dimension;
732+
$$.type_index = this->type->type_index;
733+
if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
734+
$$.type_sizeof = this->type->type_sizeof;
735+
else
736+
$$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")"));
737+
738+
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
739+
}
740+
}
704741
| s_struct_union_symbol
705742
{
706743
/* this is for named structs/unions */
@@ -1342,7 +1379,7 @@ ECPGTypedef: TYPE_P
13421379
/* an initializer specified */
13431380
initializer = 0;
13441381
}
1345-
ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
1382+
ECPGColLabel IS var_type opt_array_bounds opt_reference
13461383
{
13471384
add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0);
13481385

0 commit comments

Comments
 (0)