diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/catalog/system_functions.sql | 26 | ||||
| -rw-r--r-- | src/backend/executor/execExpr.c | 11 | ||||
| -rw-r--r-- | src/backend/executor/execExprInterp.c | 46 | ||||
| -rw-r--r-- | src/backend/jit/llvm/llvmjit_expr.c | 6 | ||||
| -rw-r--r-- | src/backend/jit/llvm/llvmjit_types.c | 1 | ||||
| -rw-r--r-- | src/backend/nodes/nodeFuncs.c | 27 | ||||
| -rw-r--r-- | src/backend/optimizer/path/costsize.c | 1 | ||||
| -rw-r--r-- | src/backend/optimizer/util/clauses.c | 39 | ||||
| -rw-r--r-- | src/backend/parser/gram.y | 59 | ||||
| -rw-r--r-- | src/backend/parser/parse_expr.c | 52 | ||||
| -rw-r--r-- | src/backend/parser/parse_target.c | 25 | ||||
| -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 |
15 files changed, 211 insertions, 336 deletions
diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index 30a048f6b0..52517a6531 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -594,6 +594,32 @@ LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE AS 'unicode_is_normalized'; +-- Functions with SQL-mandated special syntax and some defaults. +CREATE OR REPLACE FUNCTION + "current_time"(int4 DEFAULT NULL) + RETURNS timetz + LANGUAGE internal + STABLE PARALLEL SAFE +AS 'current_time'; +CREATE OR REPLACE FUNCTION + "current_timestamp"(int4 DEFAULT NULL) + RETURNS timestamptz + LANGUAGE internal + STABLE PARALLEL SAFE + AS 'current_timestamp'; +CREATE OR REPLACE FUNCTION + "localtime"(int4 DEFAULT NULL) + RETURNS time + LANGUAGE internal + STABLE PARALLEL SAFE + AS 'sql_localtime'; +CREATE OR REPLACE FUNCTION + "localtimestamp"(int4 DEFAULT NULL) + RETURNS timestamp + LANGUAGE internal + STABLE PARALLEL SAFE + AS 'sql_localtimestamp'; + -- -- The default permissions for functions mean that anyone can execute them. -- A number of functions shouldn't be executable by just anyone, but rather diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index 0ecb2f8610..81429b9f05 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -2210,17 +2210,6 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } - case T_SQLValueFunction: - { - SQLValueFunction *svf = (SQLValueFunction *) node; - - scratch.opcode = EEOP_SQLVALUEFUNCTION; - scratch.d.sqlvaluefunction.svf = svf; - - ExprEvalPushStep(state, &scratch); - break; - } - case T_XmlExpr: { XmlExpr *xexpr = (XmlExpr *) node; diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 6ebf5c287e..1dab2787b7 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -452,7 +452,6 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_DISTINCT, &&CASE_EEOP_NOT_DISTINCT, &&CASE_EEOP_NULLIF, - &&CASE_EEOP_SQLVALUEFUNCTION, &&CASE_EEOP_CURRENTOFEXPR, &&CASE_EEOP_NEXTVALUEEXPR, &&CASE_EEOP_ARRAYEXPR, @@ -1301,17 +1300,6 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } - EEO_CASE(EEOP_SQLVALUEFUNCTION) - { - /* - * Doesn't seem worthwhile to have an inline implementation - * efficiency-wise. - */ - ExecEvalSQLValueFunction(state, op); - - EEO_NEXT(); - } - EEO_CASE(EEOP_CURRENTOFEXPR) { /* error invocation uses space, and shouldn't ever occur */ @@ -2490,40 +2478,6 @@ ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext) } /* - * Evaluate a SQLValueFunction expression. - */ -void -ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op) -{ - SQLValueFunction *svf = op->d.sqlvaluefunction.svf; - - *op->resnull = false; - - switch (svf->op) - { - case SVFOP_CURRENT_DATE: - *op->resvalue = DateADTGetDatum(GetSQLCurrentDate()); - break; - case SVFOP_CURRENT_TIME: - case SVFOP_CURRENT_TIME_N: - *op->resvalue = TimeTzADTPGetDatum(GetSQLCurrentTime(svf->typmod)); - break; - case SVFOP_CURRENT_TIMESTAMP: - case SVFOP_CURRENT_TIMESTAMP_N: - *op->resvalue = TimestampTzGetDatum(GetSQLCurrentTimestamp(svf->typmod)); - break; - case SVFOP_LOCALTIME: - case SVFOP_LOCALTIME_N: - *op->resvalue = TimeADTGetDatum(GetSQLLocalTime(svf->typmod)); - break; - case SVFOP_LOCALTIMESTAMP: - case SVFOP_LOCALTIMESTAMP_N: - *op->resvalue = TimestampGetDatum(GetSQLLocalTimestamp(svf->typmod)); - break; - } -} - -/* * Raise error if a CURRENT OF expression is evaluated. * * The planner should convert CURRENT OF into a TidScan qualification, or some diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index 95d0807bdd..f114337f8e 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -1549,12 +1549,6 @@ llvm_compile_expr(ExprState *state) break; } - case EEOP_SQLVALUEFUNCTION: - build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction", - v_state, op); - LLVMBuildBr(b, opblocks[opno + 1]); - break; - case EEOP_CURRENTOFEXPR: build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr", v_state, op); diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c index 90ac6b83b5..5b416c5642 100644 --- a/src/backend/jit/llvm/llvmjit_types.c +++ b/src/backend/jit/llvm/llvmjit_types.c @@ -126,7 +126,6 @@ void *referenced_functions[] = ExecEvalRow, ExecEvalRowNotNull, ExecEvalRowNull, - ExecEvalSQLValueFunction, ExecEvalScalarArrayOp, ExecEvalHashedScalarArrayOp, ExecEvalSubPlan, diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 2585a3175c..af8620ceb7 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -210,9 +210,6 @@ exprType(const Node *expr) case T_MinMaxExpr: type = ((const MinMaxExpr *) expr)->minmaxtype; break; - case T_SQLValueFunction: - type = ((const SQLValueFunction *) expr)->type; - break; case T_XmlExpr: if (((const XmlExpr *) expr)->op == IS_DOCUMENT) type = BOOLOID; @@ -474,8 +471,6 @@ exprTypmod(const Node *expr) return typmod; } break; - case T_SQLValueFunction: - return ((const SQLValueFunction *) expr)->typmod; case T_CoerceToDomain: return ((const CoerceToDomain *) expr)->resulttypmod; case T_CoerceToDomainValue: @@ -916,10 +911,6 @@ exprCollation(const Node *expr) case T_MinMaxExpr: coll = ((const MinMaxExpr *) expr)->minmaxcollid; break; - case T_SQLValueFunction: - /* Returns a non-collatable type */ - coll = InvalidOid; - break; case T_XmlExpr: /* @@ -1140,9 +1131,6 @@ exprSetCollation(Node *expr, Oid collation) case T_MinMaxExpr: ((MinMaxExpr *) expr)->minmaxcollid = collation; break; - case T_SQLValueFunction: - Assert(collation == InvalidOid); - break; case T_XmlExpr: Assert((((XmlExpr *) expr)->op == IS_XMLSERIALIZE) ? (collation == DEFAULT_COLLATION_OID) : @@ -1426,10 +1414,6 @@ exprLocation(const Node *expr) /* GREATEST/LEAST keyword should always be the first thing */ loc = ((const MinMaxExpr *) expr)->location; break; - case T_SQLValueFunction: - /* function keyword should always be the first thing */ - loc = ((const SQLValueFunction *) expr)->location; - break; case T_XmlExpr: { const XmlExpr *xexpr = (const XmlExpr *) expr; @@ -1717,10 +1701,10 @@ set_sa_opfuncid(ScalarArrayOpExpr *opexpr) * for themselves, in case additional checks should be made, or because they * have special rules about which parts of the tree need to be visited. * - * Note: we ignore MinMaxExpr, SQLValueFunction, XmlExpr, CoerceToDomain, - * and NextValueExpr nodes, because they do not contain SQL function OIDs. - * However, they can invoke SQL-visible functions, so callers should take - * thought about how to treat them. + * Note: we ignore MinMaxExpr, XmlExpr, CoerceToDomain, and NextValueExpr + * nodes, because they do not contain SQL function OIDs. However, they can + * invoke SQL-visible functions, so callers should take thought about how + * to treat them. */ bool check_functions_in_node(Node *node, check_function_callback checker, @@ -1936,7 +1920,6 @@ expression_tree_walker_impl(Node *node, case T_Const: case T_Param: case T_CaseTestExpr: - case T_SQLValueFunction: case T_CoerceToDomainValue: case T_SetToDefault: case T_CurrentOfExpr: @@ -2673,7 +2656,6 @@ expression_tree_mutator_impl(Node *node, break; case T_Param: case T_CaseTestExpr: - case T_SQLValueFunction: case T_CoerceToDomainValue: case T_SetToDefault: case T_CurrentOfExpr: @@ -3587,7 +3569,6 @@ raw_expression_tree_walker_impl(Node *node, { case T_SetToDefault: case T_CurrentOfExpr: - case T_SQLValueFunction: case T_Integer: case T_Float: case T_Boolean: diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 4c6b1d1f55..897309d7ec 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -4603,7 +4603,6 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context) } } else if (IsA(node, MinMaxExpr) || - IsA(node, SQLValueFunction) || IsA(node, XmlExpr) || IsA(node, CoerceToDomain) || IsA(node, NextValueExpr)) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 33790a4f46..bffc8112aa 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -383,12 +383,6 @@ contain_mutable_functions_walker(Node *node, void *context) context)) return true; - if (IsA(node, SQLValueFunction)) - { - /* all variants of SQLValueFunction are stable */ - return true; - } - if (IsA(node, NextValueExpr)) { /* NextValueExpr is volatile */ @@ -537,8 +531,8 @@ contain_volatile_functions_walker(Node *node, void *context) /* * See notes in contain_mutable_functions_walker about why we treat - * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while - * SQLValueFunction is stable. Hence, none of them are of interest here. + * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable. Hence, none of + * them are of interest here. */ /* Recurse to check arguments */ @@ -583,10 +577,9 @@ contain_volatile_functions_not_nextval_walker(Node *node, void *context) /* * See notes in contain_mutable_functions_walker about why we treat - * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while - * SQLValueFunction is stable. Hence, none of them are of interest here. - * Also, since we're intentionally ignoring nextval(), presumably we - * should ignore NextValueExpr. + * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable. Hence, none of + * them are of interest here. Also, since we're intentionally ignoring + * nextval(), presumably we should ignore NextValueExpr. */ /* Recurse to check arguments */ @@ -732,8 +725,8 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context) * (Note: in principle that's wrong because a domain constraint could * contain a parallel-unsafe function; but useful constraints probably * never would have such, and assuming they do would cripple use of - * parallel query in the presence of domain types.) SQLValueFunction - * should be safe in all cases. NextValueExpr is parallel-unsafe. + * parallel query in the presence of domain types.) NextValueExpr is + * parallel-unsafe. */ if (IsA(node, CoerceToDomain)) { @@ -1180,7 +1173,6 @@ contain_leaked_vars_walker(Node *node, void *context) case T_CaseExpr: case T_CaseTestExpr: case T_RowExpr: - case T_SQLValueFunction: case T_NullTest: case T_BooleanTest: case T_NextValueExpr: @@ -3194,23 +3186,6 @@ eval_const_expressions_mutator(Node *node, newcoalesce->location = coalesceexpr->location; return (Node *) newcoalesce; } - case T_SQLValueFunction: - { - /* - * All variants of SQLValueFunction are stable, so if we are - * estimating the expression's value, we should evaluate the - * current function value. Otherwise just copy. - */ - SQLValueFunction *svf = (SQLValueFunction *) node; - - if (context->estimate) - return (Node *) evaluate_expr((Expr *) svf, - svf->type, - svf->typmod, - InvalidOid); - else - return copyObject((Node *) svf); - } case T_FieldSelect: { /* diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 9054742427..9384214942 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -198,8 +198,6 @@ static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location); static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location); static Node *makeNotExpr(Node *expr, int location); static Node *makeAArrayExpr(List *elements, int location); -static Node *makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, - int location); static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location); static List *mergeTableFuncParameters(List *func_args, List *columns); @@ -15195,39 +15193,66 @@ func_expr_common_subexpr: } | CURRENT_DATE { - $$ = makeSQLValueFunction(SVFOP_CURRENT_DATE, -1, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("current_date"), + NIL, + COERCE_SQL_SYNTAX, + @1); } | CURRENT_TIME { - $$ = makeSQLValueFunction(SVFOP_CURRENT_TIME, -1, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("current_time"), + NIL, + COERCE_SQL_SYNTAX, + @1); } | CURRENT_TIME '(' Iconst ')' { - $$ = makeSQLValueFunction(SVFOP_CURRENT_TIME_N, $3, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("current_time"), + list_make1(makeIntConst($3, @3)), + COERCE_SQL_SYNTAX, + @1); } | CURRENT_TIMESTAMP { - $$ = makeSQLValueFunction(SVFOP_CURRENT_TIMESTAMP, -1, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("current_timestamp"), + NIL, + COERCE_SQL_SYNTAX, + @1); } | CURRENT_TIMESTAMP '(' Iconst ')' { - $$ = makeSQLValueFunction(SVFOP_CURRENT_TIMESTAMP_N, $3, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("current_timestamp"), + list_make1(makeIntConst($3, @3)), + COERCE_SQL_SYNTAX, + @1); } | LOCALTIME { - $$ = makeSQLValueFunction(SVFOP_LOCALTIME, -1, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("localtime"), + NIL, + COERCE_SQL_SYNTAX, + @1); } | LOCALTIME '(' Iconst ')' { - $$ = makeSQLValueFunction(SVFOP_LOCALTIME_N, $3, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("localtime"), + list_make1(makeIntConst($3, @3)), + COERCE_SQL_SYNTAX, + @1); } | LOCALTIMESTAMP { - $$ = makeSQLValueFunction(SVFOP_LOCALTIMESTAMP, -1, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("localtimestamp"), + NIL, + COERCE_SQL_SYNTAX, + @1); } | LOCALTIMESTAMP '(' Iconst ')' { - $$ = makeSQLValueFunction(SVFOP_LOCALTIMESTAMP_N, $3, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("localtimestamp"), + list_make1(makeIntConst($3, @3)), + COERCE_SQL_SYNTAX, + @1); } | CURRENT_ROLE { @@ -18167,18 +18192,6 @@ makeAArrayExpr(List *elements, int location) } static Node * -makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, int location) -{ - SQLValueFunction *svf = makeNode(SQLValueFunction); - - svf->op = op; - /* svf->type will be filled during parse analysis */ - svf->typmod = typmod; - svf->location = location; - return (Node *) svf; -} - -static Node * makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location) { diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 0fdbf82f3a..150a8099c2 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -61,8 +61,6 @@ static Node *transformArrayExpr(ParseState *pstate, A_ArrayExpr *a, static Node *transformRowExpr(ParseState *pstate, RowExpr *r, bool allowDefault); static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c); static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m); -static Node *transformSQLValueFunction(ParseState *pstate, - SQLValueFunction *svf); static Node *transformXmlExpr(ParseState *pstate, XmlExpr *x); static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); @@ -240,11 +238,6 @@ transformExprRecurse(ParseState *pstate, Node *expr) result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr); break; - case T_SQLValueFunction: - result = transformSQLValueFunction(pstate, - (SQLValueFunction *) expr); - break; - case T_XmlExpr: result = transformXmlExpr(pstate, (XmlExpr *) expr); break; @@ -2192,51 +2185,6 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m) } static Node * -transformSQLValueFunction(ParseState *pstate, SQLValueFunction *svf) -{ - /* - * All we need to do is insert the correct result type and (where needed) - * validate the typmod, so we just modify the node in-place. - */ - switch (svf->op) - { - case SVFOP_CURRENT_DATE: - svf->type = DATEOID; - break; - case SVFOP_CURRENT_TIME: - svf->type = TIMETZOID; - break; - case SVFOP_CURRENT_TIME_N: - svf->type = TIMETZOID; - svf->typmod = anytime_typmod_check(true, svf->typmod); - break; - case SVFOP_CURRENT_TIMESTAMP: - svf->type = TIMESTAMPTZOID; - break; - case SVFOP_CURRENT_TIMESTAMP_N: - svf->type = TIMESTAMPTZOID; - svf->typmod = anytimestamp_typmod_check(true, svf->typmod); - break; - case SVFOP_LOCALTIME: - svf->type = TIMEOID; - break; - case SVFOP_LOCALTIME_N: - svf->type = TIMEOID; - svf->typmod = anytime_typmod_check(false, svf->typmod); - break; - case SVFOP_LOCALTIMESTAMP: - svf->type = TIMESTAMPOID; - break; - case SVFOP_LOCALTIMESTAMP_N: - svf->type = TIMESTAMPOID; - svf->typmod = anytimestamp_typmod_check(false, svf->typmod); - break; - } - - return (Node *) svf; -} - -static Node * transformXmlExpr(ParseState *pstate, XmlExpr *x) { XmlExpr *newx; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index f54591a987..8e0d6fd01f 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -1872,31 +1872,6 @@ FigureColnameInternal(Node *node, char **name) return 2; } break; - case T_SQLValueFunction: - /* make these act like a function or variable */ - switch (((SQLValueFunction *) node)->op) - { - case SVFOP_CURRENT_DATE: - *name = "current_date"; - return 2; - case SVFOP_CURRENT_TIME: - case SVFOP_CURRENT_TIME_N: - *name = "current_time"; - return 2; - case SVFOP_CURRENT_TIMESTAMP: - case SVFOP_CURRENT_TIMESTAMP_N: - *name = "current_timestamp"; - return 2; - case SVFOP_LOCALTIME: - case SVFOP_LOCALTIME_N: - *name = "localtime"; - return 2; - case SVFOP_LOCALTIMESTAMP: - case SVFOP_LOCALTIMESTAMP_N: - *name = "localtimestamp"; - return 2; - } - break; case T_XmlExpr: /* make SQL/XML functions act like a regular function */ switch (((XmlExpr *) node)->op) 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; |
