aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/misc.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-09-18 16:46:26 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2020-09-18 16:46:36 -0400
commit06a7c3154f5bfad65549810cc84f0e3a77b408bf (patch)
treefdfecda402a05303ec6abc6d4437924ea26fe51c /src/backend/utils/adt/misc.c
parent0811f766fd740018a72e222521553f8b22e7b3d6 (diff)
downloadpostgresql-06a7c3154f5bfad65549810cc84f0e3a77b408bf.tar.gz
postgresql-06a7c3154f5bfad65549810cc84f0e3a77b408bf.zip
Allow most keywords to be used as column labels without requiring AS.
Up to now, if you tried to omit "AS" before a column label in a SELECT list, it would only work if the column label was an IDENT, that is not any known keyword. This is rather unfriendly considering that we have so many keywords and are constantly growing more. In the wake of commit 1ed6b8956 it's possible to improve matters quite a bit. We'd originally tried to make this work by having some of the existing keyword categories be allowed without AS, but that didn't work too well, because each category contains a few special cases that don't work without AS. Instead, invent an entirely orthogonal keyword property "can be bare column label", and mark all keywords that way for which we don't get shift/reduce errors by doing so. It turns out that of our 450 current keywords, all but 39 can be made bare column labels, improving the situation by over 90%. This number might move around a little depending on future grammar work, but it's a pretty nice improvement. Mark Dilger, based on work by myself and Robert Haas; review by John Naylor Discussion: https://postgr.es/m/38ca86db-42ab-9b48-2902-337a0d6b8311@2ndquadrant.com
Diffstat (limited to 'src/backend/utils/adt/misc.c')
-rw-r--r--src/backend/utils/adt/misc.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 37c23c9155a..b2bf9fa8cbc 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -416,12 +416,16 @@ pg_get_keywords(PG_FUNCTION_ARGS)
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- tupdesc = CreateTemplateTupleDesc(3);
+ tupdesc = CreateTemplateTupleDesc(5);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word",
TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catcode",
CHAROID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 3, "catdesc",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "barelabel",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "catdesc",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 5, "baredesc",
TEXTOID, -1, 0);
funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
@@ -433,7 +437,7 @@ pg_get_keywords(PG_FUNCTION_ARGS)
if (funcctx->call_cntr < ScanKeywords.num_keywords)
{
- char *values[3];
+ char *values[5];
HeapTuple tuple;
/* cast-away-const is ugly but alternatives aren't much better */
@@ -445,26 +449,37 @@ pg_get_keywords(PG_FUNCTION_ARGS)
{
case UNRESERVED_KEYWORD:
values[1] = "U";
- values[2] = _("unreserved");
+ values[3] = _("unreserved");
break;
case COL_NAME_KEYWORD:
values[1] = "C";
- values[2] = _("unreserved (cannot be function or type name)");
+ values[3] = _("unreserved (cannot be function or type name)");
break;
case TYPE_FUNC_NAME_KEYWORD:
values[1] = "T";
- values[2] = _("reserved (can be function or type name)");
+ values[3] = _("reserved (can be function or type name)");
break;
case RESERVED_KEYWORD:
values[1] = "R";
- values[2] = _("reserved");
+ values[3] = _("reserved");
break;
default: /* shouldn't be possible */
values[1] = NULL;
- values[2] = NULL;
+ values[3] = NULL;
break;
}
+ if (ScanKeywordBareLabel[funcctx->call_cntr])
+ {
+ values[2] = "true";
+ values[4] = _("can be bare label");
+ }
+ else
+ {
+ values[2] = "false";
+ values[4] = _("requires AS");
+ }
+
tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));