Skip to content

Commit 40c24bf

Browse files
committed
Improve our ability to regurgitate SQL-syntax function calls.
The SQL spec calls out nonstandard syntax for certain function calls, for example substring() with numeric position info is supposed to be spelled "SUBSTRING(string FROM start FOR count)". We accept many of these things, but up to now would not print them in the same format, instead simplifying down to "substring"(string, start, count). That's long annoyed me because it creates an interoperability problem: we're gratuitously injecting Postgres-specific syntax into what might otherwise be a perfectly spec-compliant view definition. However, the real reason for addressing it right now is to support a planned change in the semantics of EXTRACT() a/k/a date_part(). When we switch that to returning numeric, we'll have the parser translate EXTRACT() to some new function name (might as well be "extract" if you ask me) and then teach ruleutils.c to reverse-list that per SQL spec. In this way existing calls to date_part() will continue to have the old semantics. To implement this, invent a new CoercionForm value COERCE_SQL_SYNTAX, and make the parser insert that rather than COERCE_EXPLICIT_CALL when the input has SQL-spec decoration. (But if the input has the form of a plain function call, continue to mark it COERCE_EXPLICIT_CALL, even if it's calling one of these functions.) Then ruleutils.c recognizes COERCE_SQL_SYNTAX as a cue to emit SQL call syntax. It can know which decoration to emit using hard-wired knowledge about the functions that could be called this way. (While this solution isn't extensible without manual additions, neither is the grammar, so this doesn't seem unmaintainable.) Notice that this solution will reverse-list a function call with SQL decoration only if it was entered that way; so dump-and-reload will not by itself produce any changes in the appearance of views. This requires adding a CoercionForm field to struct FuncCall. (I couldn't resist the temptation to rearrange that struct's field order a tad while I was at it.) FuncCall doesn't appear in stored rules, so that change isn't a reason for a catversion bump, but I did one anyway because the new enum value for CoercionForm fields could confuse old backend code. Possible future work: * Perhaps CoercionForm should now be renamed to DisplayForm, or something like that, to reflect its more general meaning. This'd require touching a couple hundred places, so it's not clear it's worth the code churn. * The SQLValueFunction node type, which was invented partly for the same goal of improving SQL-compatibility of view output, could perhaps be replaced with regular function calls marked with COERCE_SQL_SYNTAX. It's unclear if this would be a net code savings, however. Discussion: https://postgr.es/m/[email protected]
1 parent f21636e commit 40c24bf

File tree

17 files changed

+480
-71
lines changed

17 files changed

+480
-71
lines changed

src/backend/nodes/copyfuncs.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -2682,11 +2682,12 @@ _copyFuncCall(const FuncCall *from)
26822682
COPY_NODE_FIELD(args);
26832683
COPY_NODE_FIELD(agg_order);
26842684
COPY_NODE_FIELD(agg_filter);
2685+
COPY_NODE_FIELD(over);
26852686
COPY_SCALAR_FIELD(agg_within_group);
26862687
COPY_SCALAR_FIELD(agg_star);
26872688
COPY_SCALAR_FIELD(agg_distinct);
26882689
COPY_SCALAR_FIELD(func_variadic);
2689-
COPY_NODE_FIELD(over);
2690+
COPY_SCALAR_FIELD(funcformat);
26902691
COPY_LOCATION_FIELD(location);
26912692

26922693
return newnode;

src/backend/nodes/equalfuncs.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -2369,11 +2369,12 @@ _equalFuncCall(const FuncCall *a, const FuncCall *b)
23692369
COMPARE_NODE_FIELD(args);
23702370
COMPARE_NODE_FIELD(agg_order);
23712371
COMPARE_NODE_FIELD(agg_filter);
2372+
COMPARE_NODE_FIELD(over);
23722373
COMPARE_SCALAR_FIELD(agg_within_group);
23732374
COMPARE_SCALAR_FIELD(agg_star);
23742375
COMPARE_SCALAR_FIELD(agg_distinct);
23752376
COMPARE_SCALAR_FIELD(func_variadic);
2376-
COMPARE_NODE_FIELD(over);
2377+
COMPARE_SCALAR_FIELD(funcformat);
23772378
COMPARE_LOCATION_FIELD(location);
23782379

23792380
return true;

src/backend/nodes/makefuncs.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -582,19 +582,20 @@ makeDefElemExtended(char *nameSpace, char *name, Node *arg,
582582
* supply. Any non-default parameters have to be inserted by the caller.
583583
*/
584584
FuncCall *
585-
makeFuncCall(List *name, List *args, int location)
585+
makeFuncCall(List *name, List *args, CoercionForm funcformat, int location)
586586
{
587587
FuncCall *n = makeNode(FuncCall);
588588

589589
n->funcname = name;
590590
n->args = args;
591591
n->agg_order = NIL;
592592
n->agg_filter = NULL;
593+
n->over = NULL;
593594
n->agg_within_group = false;
594595
n->agg_star = false;
595596
n->agg_distinct = false;
596597
n->func_variadic = false;
597-
n->over = NULL;
598+
n->funcformat = funcformat;
598599
n->location = location;
599600
return n;
600601
}

src/backend/nodes/outfuncs.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -2765,11 +2765,12 @@ _outFuncCall(StringInfo str, const FuncCall *node)
27652765
WRITE_NODE_FIELD(args);
27662766
WRITE_NODE_FIELD(agg_order);
27672767
WRITE_NODE_FIELD(agg_filter);
2768+
WRITE_NODE_FIELD(over);
27682769
WRITE_BOOL_FIELD(agg_within_group);
27692770
WRITE_BOOL_FIELD(agg_star);
27702771
WRITE_BOOL_FIELD(agg_distinct);
27712772
WRITE_BOOL_FIELD(func_variadic);
2772-
WRITE_NODE_FIELD(over);
2773+
WRITE_ENUM_FIELD(funcformat, CoercionForm);
27732774
WRITE_LOCATION_FIELD(location);
27742775
}
27752776

0 commit comments

Comments
 (0)