aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-08-16 20:33:01 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2016-08-16 20:33:01 -0400
commit0bb51aa96783e8a6c473c2b5e3725e23e95db834 (patch)
treef4d4077257f5a4937fefafd0fe6f914f5e4027fd /src/backend/executor
parent4bc4cfe3bd186b4a1d1b01279bfd0e6ab11268b2 (diff)
downloadpostgresql-0bb51aa96783e8a6c473c2b5e3725e23e95db834.tar.gz
postgresql-0bb51aa96783e8a6c473c2b5e3725e23e95db834.zip
Improve parsetree representation of special functions such as CURRENT_DATE.
We implement a dozen or so parameterless functions that the SQL standard defines special syntax for. Up to now, that was done by converting them into more or less ad-hoc constructs such as "'now'::text::date". That's messy for multiple reasons: it exposes what should be implementation details to users, and performance is worse than it needs to be in several cases. To improve matters, invent a new expression node type SQLValueFunction that can represent any of these parameterless functions. Bump catversion because this changes stored parsetrees for rules. Discussion: <30058.1463091294@sss.pgh.pa.us>
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execQual.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index cbb76d1f1cd..743e7d636a0 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -53,8 +53,10 @@
#include "pgstat.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/date.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
+#include "utils/timestamp.h"
#include "utils/typcache.h"
#include "utils/xml.h"
@@ -147,6 +149,9 @@ static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalSQLValueFunction(ExprState *svfExpr,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
@@ -3531,6 +3536,75 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
}
/* ----------------------------------------------------------------
+ * ExecEvalSQLValueFunction
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalSQLValueFunction(ExprState *svfExpr,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone)
+{
+ Datum result = (Datum) 0;
+ SQLValueFunction *svf = (SQLValueFunction *) svfExpr->expr;
+ FunctionCallInfoData fcinfo;
+
+ if (isDone)
+ *isDone = ExprSingleResult;
+ *isNull = false;
+
+ /*
+ * Note: current_schema() can return NULL. current_user() etc currently
+ * cannot, but might as well code those cases the same way for safety.
+ */
+ switch (svf->op)
+ {
+ case SVFOP_CURRENT_DATE:
+ result = DateADTGetDatum(GetSQLCurrentDate());
+ break;
+ case SVFOP_CURRENT_TIME:
+ case SVFOP_CURRENT_TIME_N:
+ result = TimeTzADTPGetDatum(GetSQLCurrentTime(svf->typmod));
+ break;
+ case SVFOP_CURRENT_TIMESTAMP:
+ case SVFOP_CURRENT_TIMESTAMP_N:
+ result = TimestampTzGetDatum(GetSQLCurrentTimestamp(svf->typmod));
+ break;
+ case SVFOP_LOCALTIME:
+ case SVFOP_LOCALTIME_N:
+ result = TimeADTGetDatum(GetSQLLocalTime(svf->typmod));
+ break;
+ case SVFOP_LOCALTIMESTAMP:
+ case SVFOP_LOCALTIMESTAMP_N:
+ result = TimestampGetDatum(GetSQLLocalTimestamp(svf->typmod));
+ break;
+ case SVFOP_CURRENT_ROLE:
+ case SVFOP_CURRENT_USER:
+ case SVFOP_USER:
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ result = current_user(&fcinfo);
+ *isNull = fcinfo.isnull;
+ break;
+ case SVFOP_SESSION_USER:
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ result = session_user(&fcinfo);
+ *isNull = fcinfo.isnull;
+ break;
+ case SVFOP_CURRENT_CATALOG:
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ result = current_database(&fcinfo);
+ *isNull = fcinfo.isnull;
+ break;
+ case SVFOP_CURRENT_SCHEMA:
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ result = current_schema(&fcinfo);
+ *isNull = fcinfo.isnull;
+ break;
+ }
+
+ return result;
+}
+
+/* ----------------------------------------------------------------
* ExecEvalXml
* ----------------------------------------------------------------
*/
@@ -5086,6 +5160,10 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) mstate;
}
break;
+ case T_SQLValueFunction:
+ state = (ExprState *) makeNode(ExprState);
+ state->evalfunc = ExecEvalSQLValueFunction;
+ break;
case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;