diff options
| author | Michael Paquier <michael@paquier.xyz> | 2022-11-21 18:31:59 +0900 |
|---|---|---|
| committer | Michael Paquier <michael@paquier.xyz> | 2022-11-21 18:31:59 +0900 |
| commit | f193883fc9cebe8fa20359b0797832837a788112 (patch) | |
| tree | b53cd2d5a291d6d7ec546ca645901c4ee4334fe9 /src/backend/utils | |
| parent | 240e0dbacd390a8465552e27c5af11f67d747adb (diff) | |
| download | postgresql-f193883fc9cebe8fa20359b0797832837a788112.tar.gz | |
Replace SQLValueFunction by COERCE_SQL_SYNTAX
This switch impacts 9 patterns related to a SQL-mandated special syntax
for function calls:
- LOCALTIME [ ( typmod ) ]
- LOCALTIMESTAMP [ ( typmod ) ]
- CURRENT_TIME [ ( typmod ) ]
- CURRENT_TIMESTAMP [ ( typmod ) ]
- CURRENT_DATE
Five new entries are added to pg_proc to compensate the removal of
SQLValueFunction to provide backward-compatibility and making this
change transparent for the end-user (for example for the attribute
generated when a keyword is specified in a SELECT or in a FROM clause
without an alias, or when specifying something else than an Iconst to
the parser).
The parser included a set of checks coming from the files in charge of
holding the C functions used for the SQLValueFunction calls (as of
transformSQLValueFunction()), which are now moved within each function's
execution path, so this reduces the dependencies between the execution
and the parsing steps. As of this change, all the SQL keywords use the
same paths for their work, relying only on COERCE_SQL_SYNTAX. Like
fb32748, no performance difference has been noticed, while the perf
profiles get reduced with ExecEvalSQLValueFunction() gone.
Bump catalog version.
Reviewed-by: Corey Huinker, Ted Yu
Discussion: https://postgr.es/m/YzaG3MoryCguUOym@paquier.xyz
Diffstat (limited to 'src/backend/utils')
| -rw-r--r-- | src/backend/utils/adt/date.c | 81 | ||||
| -rw-r--r-- | src/backend/utils/adt/ruleutils.c | 92 | ||||
| -rw-r--r-- | src/backend/utils/adt/timestamp.c | 72 | ||||
| -rw-r--r-- | src/backend/utils/misc/queryjumble.c | 9 |
4 files changed, 138 insertions, 116 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index a2bdde0459..10c11e00db 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -46,27 +46,6 @@ /* common code for timetypmodin and timetztypmodin */ static int32 -anytime_typmodin(bool istz, ArrayType *ta) -{ - int32 *tl; - int n; - - tl = ArrayGetIntegerTypmods(ta, &n); - - /* - * we're not too tense about good error message here because grammar - * shouldn't allow wrong number of modifiers for TIME - */ - if (n != 1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid type modifier"))); - - return anytime_typmod_check(istz, tl[0]); -} - -/* exported so parse_expr.c can use it */ -int32 anytime_typmod_check(bool istz, int32 typmod) { if (typmod < 0) @@ -87,6 +66,26 @@ anytime_typmod_check(bool istz, int32 typmod) return typmod; } +static int32 +anytime_typmodin(bool istz, ArrayType *ta) +{ + int32 *tl; + int n; + + tl = ArrayGetIntegerTypmods(ta, &n); + + /* + * we're not too tense about good error message here because grammar + * shouldn't allow wrong number of modifiers for TIME + */ + if (n != 1) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid type modifier"))); + + return anytime_typmod_check(istz, tl[0]); +} + /* common code for timetypmodout and timetztypmodout */ static char * anytime_typmodout(bool istz, int32 typmod) @@ -296,10 +295,10 @@ EncodeSpecialDate(DateADT dt, char *str) /* - * GetSQLCurrentDate -- implements CURRENT_DATE + * current_date -- implements CURRENT_DATE */ -DateADT -GetSQLCurrentDate(void) +Datum +current_date(PG_FUNCTION_ARGS) { struct pg_tm tm; @@ -325,46 +324,62 @@ GetSQLCurrentDate(void) cache_mday = tm.tm_mday; } - return cache_date; + return DateADTGetDatum(cache_date); } /* - * GetSQLCurrentTime -- implements CURRENT_TIME, CURRENT_TIME(n) + * current_time -- implements CURRENT_TIME, CURRENT_TIME(n) */ -TimeTzADT * -GetSQLCurrentTime(int32 typmod) +Datum +current_time(PG_FUNCTION_ARGS) { TimeTzADT *result; struct pg_tm tt, *tm = &tt; fsec_t fsec; int tz; + int32 typmod = -1; + + if (!PG_ARGISNULL(0)) + { + typmod = PG_GETARG_INT32(0); + anytime_typmod_check(true, typmod); + } GetCurrentTimeUsec(tm, &fsec, &tz); result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); tm2timetz(tm, fsec, tz, result); AdjustTimeForTypmod(&(result->time), typmod); - return result; + + return TimeTzADTPGetDatum(result); } /* - * GetSQLLocalTime -- implements LOCALTIME, LOCALTIME(n) + * sql_localtime -- implements LOCALTIME, LOCALTIME(n) */ -TimeADT -GetSQLLocalTime(int32 typmod) +Datum +sql_localtime(PG_FUNCTION_ARGS) { TimeADT result; struct pg_tm tt, *tm = &tt; fsec_t fsec; int tz; + int32 typmod = -1; + + if (!PG_ARGISNULL(0)) + { + typmod = PG_GETARG_INT32(0); + anytime_typmod_check(false, typmod); + } GetCurrentTimeUsec(tm, &fsec, &tz); tm2time(tm, fsec, &result); AdjustTimeForTypmod(&result, typmod); - return result; + + return TimeADTGetDatum(result); } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 129f3333fb..f3ea36a231 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -8150,7 +8150,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) case T_RowExpr: case T_CoalesceExpr: case T_MinMaxExpr: - case T_SQLValueFunction: case T_XmlExpr: case T_NextValueExpr: case T_NullIfExpr: @@ -9130,49 +9129,6 @@ get_rule_expr(Node *node, deparse_context *context, } break; - case T_SQLValueFunction: - { - SQLValueFunction *svf = (SQLValueFunction *) node; - - /* - * Note: this code knows that typmod for time, timestamp, and - * timestamptz just prints as integer. - */ - switch (svf->op) - { - case SVFOP_CURRENT_DATE: - appendStringInfoString(buf, "CURRENT_DATE"); - break; - case SVFOP_CURRENT_TIME: - appendStringInfoString(buf, "CURRENT_TIME"); - break; - case SVFOP_CURRENT_TIME_N: - appendStringInfo(buf, "CURRENT_TIME(%d)", svf->typmod); - break; - case SVFOP_CURRENT_TIMESTAMP: - appendStringInfoString(buf, "CURRENT_TIMESTAMP"); - break; - case SVFOP_CURRENT_TIMESTAMP_N: - appendStringInfo(buf, "CURRENT_TIMESTAMP(%d)", - svf->typmod); - break; - case SVFOP_LOCALTIME: - appendStringInfoString(buf, "LOCALTIME"); - break; - case SVFOP_LOCALTIME_N: - appendStringInfo(buf, "LOCALTIME(%d)", svf->typmod); - break; - case SVFOP_LOCALTIMESTAMP: - appendStringInfoString(buf, "LOCALTIMESTAMP"); - break; - case SVFOP_LOCALTIMESTAMP_N: - appendStringInfo(buf, "LOCALTIMESTAMP(%d)", - svf->typmod); - break; - } - } - break; - case T_XmlExpr: { XmlExpr *xexpr = (XmlExpr *) node; @@ -9698,7 +9654,6 @@ looks_like_function(Node *node) case T_NullIfExpr: case T_CoalesceExpr: case T_MinMaxExpr: - case T_SQLValueFunction: case T_XmlExpr: /* these are all accepted by func_expr_common_subexpr */ return true; @@ -10043,6 +9998,33 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context) } /* + * get_func_sql_syntax_time + * + * Parse back argument of SQL-syntax function call related to a time or a + * timestamp. These require a specific handling when their typmod is given + * by the function caller through their SQL keyword. + */ +static void +get_func_sql_syntax_time(List *args, deparse_context *context) +{ + StringInfo buf = context->buf; + Const *cons; + + if (list_length(args) != 1) + return; + + cons = (Const *) linitial(args); + Assert(IsA(cons, Const)); + + if (!cons->constisnull) + { + appendStringInfoString(buf, "("); + get_rule_expr((Node *) cons, context, false); + appendStringInfoString(buf, ")"); + } +} + +/* * get_func_sql_syntax - Parse back a SQL-syntax function call * * Returns true if we successfully deparsed, false if we did not @@ -10292,6 +10274,26 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context) appendStringInfoString(buf, "SYSTEM_USER"); return true; + case F_CURRENT_DATE: + appendStringInfoString(buf, "CURRENT_DATE"); + return true; + case F_CURRENT_TIME: + appendStringInfoString(buf, "CURRENT_TIME"); + get_func_sql_syntax_time(expr->args, context); + return true; + case F_CURRENT_TIMESTAMP: + appendStringInfoString(buf, "CURRENT_TIMESTAMP"); + get_func_sql_syntax_time(expr->args, context); + return true; + case F_LOCALTIME: + appendStringInfoString(buf, "LOCALTIME"); + get_func_sql_syntax_time(expr->args, context); + return true; + case F_LOCALTIMESTAMP: + appendStringInfoString(buf, "LOCALTIMESTAMP"); + get_func_sql_syntax_time(expr->args, context); + return true; + case F_XMLEXISTS: /* XMLEXISTS ... extra parens because args are c_expr */ appendStringInfoString(buf, "XMLEXISTS(("); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index d8552a1f18..ef92323fd0 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -81,27 +81,6 @@ static Timestamp timestamptz2timestamp(TimestampTz timestamp); /* common code for timestamptypmodin and timestamptztypmodin */ static int32 -anytimestamp_typmodin(bool istz, ArrayType *ta) -{ - int32 *tl; - int n; - - tl = ArrayGetIntegerTypmods(ta, &n); - - /* - * we're not too tense about good error message here because grammar - * shouldn't allow wrong number of modifiers for TIMESTAMP - */ - if (n != 1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid type modifier"))); - - return anytimestamp_typmod_check(istz, tl[0]); -} - -/* exported so parse_expr.c can use it */ -int32 anytimestamp_typmod_check(bool istz, int32 typmod) { if (typmod < 0) @@ -122,6 +101,26 @@ anytimestamp_typmod_check(bool istz, int32 typmod) return typmod; } +static int32 +anytimestamp_typmodin(bool istz, ArrayType *ta) +{ + int32 *tl; + int n; + + tl = ArrayGetIntegerTypmods(ta, &n); + + /* + * we're not too tense about good error message here because grammar + * shouldn't allow wrong number of modifiers for TIMESTAMP + */ + if (n != 1) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid type modifier"))); + + return anytimestamp_typmod_check(istz, tl[0]); +} + /* common code for timestamptypmodout and timestamptztypmodout */ static char * anytimestamp_typmodout(bool istz, int32 typmod) @@ -1586,33 +1585,48 @@ GetCurrentTimestamp(void) } /* - * GetSQLCurrentTimestamp -- implements CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(n) + * current_timestamp -- implements CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(n) */ -TimestampTz -GetSQLCurrentTimestamp(int32 typmod) +Datum +current_timestamp(PG_FUNCTION_ARGS) { TimestampTz ts; + int32 typmod = -1; + + if (!PG_ARGISNULL(0)) + { + typmod = PG_GETARG_INT32(0); + anytimestamp_typmod_check(true, typmod); + } ts = GetCurrentTransactionStartTimestamp(); if (typmod >= 0) AdjustTimestampForTypmod(&ts, typmod); - return ts; + return TimestampTzGetDatum(ts); } /* - * GetSQLLocalTimestamp -- implements LOCALTIMESTAMP, LOCALTIMESTAMP(n) + * sql_localtimestamp -- implements LOCALTIMESTAMP, LOCALTIMESTAMP(n) */ -Timestamp -GetSQLLocalTimestamp(int32 typmod) +Datum +sql_localtimestamp(PG_FUNCTION_ARGS) { Timestamp ts; + int32 typmod = -1; + + if (!PG_ARGISNULL(0)) + { + typmod = PG_GETARG_INT32(0); + anytimestamp_typmod_check(false, typmod); + } ts = timestamptz2timestamp(GetCurrentTransactionStartTimestamp()); if (typmod >= 0) AdjustTimestampForTypmod(&ts, typmod); - return ts; + return TimestampGetDatum(ts); } + /* * timeofday(*) -- returns the current time as a text. */ diff --git a/src/backend/utils/misc/queryjumble.c b/src/backend/utils/misc/queryjumble.c index a8508463e7..0ace74de78 100644 --- a/src/backend/utils/misc/queryjumble.c +++ b/src/backend/utils/misc/queryjumble.c @@ -606,15 +606,6 @@ JumbleExpr(JumbleState *jstate, Node *node) JumbleExpr(jstate, (Node *) mmexpr->args); } break; - case T_SQLValueFunction: - { - SQLValueFunction *svf = (SQLValueFunction *) node; - - APP_JUMB(svf->op); - /* type is fully determined by op */ - APP_JUMB(svf->typmod); - } - break; case T_XmlExpr: { XmlExpr *xexpr = (XmlExpr *) node; |
