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
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;
&&CASE_EEOP_DISTINCT,
&&CASE_EEOP_NOT_DISTINCT,
&&CASE_EEOP_NULLIF,
- &&CASE_EEOP_SQLVALUEFUNCTION,
&&CASE_EEOP_CURRENTOFEXPR,
&&CASE_EEOP_NEXTVALUEEXPR,
&&CASE_EEOP_ARRAYEXPR,
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 */
errmsg("no value found for parameter %d", paramId)));
}
-/*
- * 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.
*
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);
ExecEvalRow,
ExecEvalRowNotNull,
ExecEvalRowNull,
- ExecEvalSQLValueFunction,
ExecEvalScalarArrayOp,
ExecEvalHashedScalarArrayOp,
ExecEvalSubPlan,
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;
return typmod;
}
break;
- case T_SQLValueFunction:
- return ((const SQLValueFunction *) expr)->typmod;
case T_CoerceToDomain:
return ((const CoerceToDomain *) expr)->resulttypmod;
case T_CoerceToDomainValue:
case T_MinMaxExpr:
coll = ((const MinMaxExpr *) expr)->minmaxcollid;
break;
- case T_SQLValueFunction:
- /* Returns a non-collatable type */
- coll = InvalidOid;
- break;
case T_XmlExpr:
/*
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) :
/* 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;
* 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,
case T_Const:
case T_Param:
case T_CaseTestExpr:
- case T_SQLValueFunction:
case T_CoerceToDomainValue:
case T_SetToDefault:
case T_CurrentOfExpr:
break;
case T_Param:
case T_CaseTestExpr:
- case T_SQLValueFunction:
case T_CoerceToDomainValue:
case T_SetToDefault:
case T_CurrentOfExpr:
{
case T_SetToDefault:
case T_CurrentOfExpr:
- case T_SQLValueFunction:
case T_Integer:
case T_Float:
case T_Boolean:
}
}
else if (IsA(node, MinMaxExpr) ||
- IsA(node, SQLValueFunction) ||
IsA(node, XmlExpr) ||
IsA(node, CoerceToDomain) ||
IsA(node, NextValueExpr))
context))
return true;
- if (IsA(node, SQLValueFunction))
- {
- /* all variants of SQLValueFunction are stable */
- return true;
- }
-
if (IsA(node, NextValueExpr))
{
/* NextValueExpr is volatile */
/*
* 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 */
/*
* 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 */
* (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))
{
case T_CaseExpr:
case T_CaseTestExpr:
case T_RowExpr:
- case T_SQLValueFunction:
case T_NullTest:
case T_BooleanTest:
case T_NextValueExpr:
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:
{
/*
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);
}
| 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
{
return (Node *) n;
}
-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)
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);
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
break;
- case T_SQLValueFunction:
- result = transformSQLValueFunction(pstate,
- (SQLValueFunction *) expr);
- break;
-
case T_XmlExpr:
result = transformXmlExpr(pstate, (XmlExpr *) expr);
break;
return (Node *) newm;
}
-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)
{
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)
/* 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)
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)
/*
- * GetSQLCurrentDate -- implements CURRENT_DATE
+ * current_date -- implements CURRENT_DATE
*/
-DateADT
-GetSQLCurrentDate(void)
+Datum
+current_date(PG_FUNCTION_ARGS)
{
struct pg_tm tm;
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);
}
case T_RowExpr:
case T_CoalesceExpr:
case T_MinMaxExpr:
- case T_SQLValueFunction:
case T_XmlExpr:
case T_NextValueExpr:
case T_NullIfExpr:
}
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;
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;
}
}
+/*
+ * 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
*
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((");
/* 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)
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)
}
/*
- * 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.
*/
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;
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202211201
+#define CATALOG_VERSION_NO 202211211
#endif
{ oid => '9977', descr => 'system user name',
proname => 'system_user', provolatile => 's', prorettype => 'text',
proargtypes => '', prosrc => 'system_user' },
+{ oid => '9978', descr => 'current date',
+ proname => 'current_date', provolatile => 's', prorettype => 'date',
+ proargtypes => '', prosrc => 'current_date' },
+{ oid => '9979', descr => 'current time',
+ proname => 'current_time', proisstrict => 'f', provolatile => 's',
+ prorettype => 'timetz', proargtypes => 'int4', prosrc => 'current_time' },
+{ oid => '9980', descr => 'current timestamp',
+ proname => 'current_timestamp', proisstrict => 'f', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => 'int4',
+ prosrc => 'current_timestamp' },
+{ oid => '9981', descr => 'local time',
+ proname => 'localtime', proisstrict => 'f', provolatile => 's',
+ prorettype => 'time', proargtypes => 'int4', prosrc => 'sql_localtime' },
+{ oid => '9982', descr => 'local timestamp',
+ proname => 'localtimestamp', proisstrict => 'f', provolatile => 's',
+ prorettype => 'timestamp', proargtypes => 'int4',
+ prosrc => 'sql_localtimestamp' },
{ oid => '744',
proname => 'array_eq', prorettype => 'bool',
EEOP_DISTINCT,
EEOP_NOT_DISTINCT,
EEOP_NULLIF,
- EEOP_SQLVALUEFUNCTION,
EEOP_CURRENTOFEXPR,
EEOP_NEXTVALUEEXPR,
EEOP_ARRAYEXPR,
FunctionCallInfo fcinfo_data_in;
} iocoerce;
- /* for EEOP_SQLVALUEFUNCTION */
- struct
- {
- SQLValueFunction *svf;
- } sqlvaluefunction;
-
/* for EEOP_NEXTVALUEEXPR */
struct
{
ExprContext *econtext);
extern void ExecEvalParamExtern(ExprState *state, ExprEvalStep *op,
ExprContext *econtext);
-extern void ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op);
extern void ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op);
extern void ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op);
extern void ExecEvalRowNull(ExprState *state, ExprEvalStep *op,
int location; /* token location, or -1 if unknown */
} MinMaxExpr;
-/*
- * SQLValueFunction - parameterless functions with special grammar productions
- *
- * The SQL standard categorizes some of these as <datetime value function>
- * and others as <general value specification>. We call 'em SQLValueFunctions
- * for lack of a better term. We store type and typmod of the result so that
- * some code doesn't need to know each function individually, and because
- * we would need to store typmod anyway for some of the datetime functions.
- * Note that currently, all variants return non-collating datatypes, so we do
- * not need a collation field; also, all these functions are stable.
- */
-typedef enum SQLValueFunctionOp
-{
- SVFOP_CURRENT_DATE,
- SVFOP_CURRENT_TIME,
- SVFOP_CURRENT_TIME_N,
- SVFOP_CURRENT_TIMESTAMP,
- SVFOP_CURRENT_TIMESTAMP_N,
- SVFOP_LOCALTIME,
- SVFOP_LOCALTIME_N,
- SVFOP_LOCALTIMESTAMP,
- SVFOP_LOCALTIMESTAMP_N
-} SQLValueFunctionOp;
-
-typedef struct SQLValueFunction
-{
- Expr xpr;
- SQLValueFunctionOp op; /* which function this is */
- Oid type; /* result type/typmod */
- int32 typmod;
- int location; /* token location, or -1 if unknown */
-} SQLValueFunction;
-
/*
* XmlExpr - various SQL/XML functions requiring special grammar productions
*
/* date.c */
-extern int32 anytime_typmod_check(bool istz, int32 typmod);
extern double date2timestamp_no_overflow(DateADT dateVal);
extern Timestamp date2timestamp_opt_overflow(DateADT dateVal, int *overflow);
extern TimestampTz date2timestamptz_opt_overflow(DateADT dateVal, int *overflow);
extern int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2);
extern void EncodeSpecialDate(DateADT dt, char *str);
-extern DateADT GetSQLCurrentDate(void);
-extern TimeTzADT *GetSQLCurrentTime(int32 typmod);
-extern TimeADT GetSQLLocalTime(int32 typmod);
extern int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec);
extern int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp);
extern int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result);
/* Internal routines (not fmgr-callable) */
-extern int32 anytimestamp_typmod_check(bool istz, int32 typmod);
-
extern TimestampTz GetCurrentTimestamp(void);
-extern TimestampTz GetSQLCurrentTimestamp(int32 typmod);
-extern Timestamp GetSQLLocalTimestamp(int32 typmod);
extern void TimestampDifference(TimestampTz start_time, TimestampTz stop_time,
long *secs, int *microsecs);
extern long TimestampDifferenceMilliseconds(TimestampTz start_time,
-- expression evaluation tests that don't fit into a more specific file
--
--
--- Tests for SQLValueFunction
+-- Tests for various FuncCalls with COERCE_SQL_SYNTAX.
--
-- current_date (always matches because of transactional behaviour)
SELECT date(now())::text = current_date::text;
--
--
--- Tests for SQLValueFunction
+-- Tests for various FuncCalls with COERCE_SQL_SYNTAX.
--
SQLFunctionCachePtr
SQLFunctionParseInfo
SQLFunctionParseInfoPtr
-SQLValueFunction
-SQLValueFunctionOp
SSL
SSLExtensionInfoContext
SSL_CTX