1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-30 06:01:21 +03:00

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>
This commit is contained in:
Tom Lane
2016-08-16 20:33:01 -04:00
parent 4bc4cfe3bd
commit 0bb51aa967
24 changed files with 626 additions and 168 deletions

View File

@@ -1752,6 +1752,22 @@ _copyMinMaxExpr(const MinMaxExpr *from)
return newnode;
}
/*
* _copySQLValueFunction
*/
static SQLValueFunction *
_copySQLValueFunction(const SQLValueFunction *from)
{
SQLValueFunction *newnode = makeNode(SQLValueFunction);
COPY_SCALAR_FIELD(op);
COPY_SCALAR_FIELD(type);
COPY_SCALAR_FIELD(typmod);
COPY_LOCATION_FIELD(location);
return newnode;
}
/*
* _copyXmlExpr
*/
@@ -4525,6 +4541,9 @@ copyObject(const void *from)
case T_MinMaxExpr:
retval = _copyMinMaxExpr(from);
break;
case T_SQLValueFunction:
retval = _copySQLValueFunction(from);
break;
case T_XmlExpr:
retval = _copyXmlExpr(from);
break;

View File

@@ -619,6 +619,17 @@ _equalMinMaxExpr(const MinMaxExpr *a, const MinMaxExpr *b)
return true;
}
static bool
_equalSQLValueFunction(const SQLValueFunction *a, const SQLValueFunction *b)
{
COMPARE_SCALAR_FIELD(op);
COMPARE_SCALAR_FIELD(type);
COMPARE_SCALAR_FIELD(typmod);
COMPARE_LOCATION_FIELD(location);
return true;
}
static bool
_equalXmlExpr(const XmlExpr *a, const XmlExpr *b)
{
@@ -2842,6 +2853,9 @@ equal(const void *a, const void *b)
case T_MinMaxExpr:
retval = _equalMinMaxExpr(a, b);
break;
case T_SQLValueFunction:
retval = _equalSQLValueFunction(a, b);
break;
case T_XmlExpr:
retval = _equalXmlExpr(a, b);
break;

View File

@@ -218,6 +218,9 @@ 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;
@@ -479,6 +482,8 @@ 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:
@@ -718,6 +723,8 @@ expression_returns_set_walker(Node *node, void *context)
return false;
if (IsA(node, MinMaxExpr))
return false;
if (IsA(node, SQLValueFunction))
return false;
if (IsA(node, XmlExpr))
return false;
@@ -883,6 +890,9 @@ exprCollation(const Node *expr)
case T_MinMaxExpr:
coll = ((const MinMaxExpr *) expr)->minmaxcollid;
break;
case T_SQLValueFunction:
coll = InvalidOid; /* all cases return non-collatable types */
break;
case T_XmlExpr:
/*
@@ -1091,6 +1101,9 @@ exprSetCollation(Node *expr, Oid collation)
case T_MinMaxExpr:
((MinMaxExpr *) expr)->minmaxcollid = collation;
break;
case T_SQLValueFunction:
Assert(!OidIsValid(collation)); /* no collatable results */
break;
case T_XmlExpr:
Assert((((XmlExpr *) expr)->op == IS_XMLSERIALIZE) ?
(collation == DEFAULT_COLLATION_OID) :
@@ -1364,6 +1377,10 @@ 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;
@@ -1633,9 +1650,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, XmlExpr, and CoerceToDomain 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, SQLValueFunction, XmlExpr, and CoerceToDomain
* 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,
@@ -1859,6 +1877,7 @@ expression_tree_walker(Node *node,
case T_CaseTestExpr:
case T_SetToDefault:
case T_CurrentOfExpr:
case T_SQLValueFunction:
case T_RangeTblRef:
case T_SortGroupClause:
/* primitive node types with no expression subnodes */
@@ -2433,6 +2452,7 @@ expression_tree_mutator(Node *node,
case T_CaseTestExpr:
case T_SetToDefault:
case T_CurrentOfExpr:
case T_SQLValueFunction:
case T_RangeTblRef:
case T_SortGroupClause:
return (Node *) copyObject(node);
@@ -3197,6 +3217,7 @@ raw_expression_tree_walker(Node *node,
{
case T_SetToDefault:
case T_CurrentOfExpr:
case T_SQLValueFunction:
case T_Integer:
case T_Float:
case T_String:

View File

@@ -1423,6 +1423,17 @@ _outMinMaxExpr(StringInfo str, const MinMaxExpr *node)
WRITE_LOCATION_FIELD(location);
}
static void
_outSQLValueFunction(StringInfo str, const SQLValueFunction *node)
{
WRITE_NODE_TYPE("SQLVALUEFUNCTION");
WRITE_ENUM_FIELD(op, SQLValueFunctionOp);
WRITE_OID_FIELD(type);
WRITE_INT_FIELD(typmod);
WRITE_LOCATION_FIELD(location);
}
static void
_outXmlExpr(StringInfo str, const XmlExpr *node)
{
@@ -3522,6 +3533,9 @@ outNode(StringInfo str, const void *obj)
case T_MinMaxExpr:
_outMinMaxExpr(str, obj);
break;
case T_SQLValueFunction:
_outSQLValueFunction(str, obj);
break;
case T_XmlExpr:
_outXmlExpr(str, obj);
break;

View File

@@ -1041,6 +1041,22 @@ _readMinMaxExpr(void)
READ_DONE();
}
/*
* _readSQLValueFunction
*/
static SQLValueFunction *
_readSQLValueFunction(void)
{
READ_LOCALS(SQLValueFunction);
READ_ENUM_FIELD(op, SQLValueFunctionOp);
READ_OID_FIELD(type);
READ_INT_FIELD(typmod);
READ_LOCATION_FIELD(location);
READ_DONE();
}
/*
* _readXmlExpr
*/
@@ -2348,6 +2364,8 @@ parseNodeString(void)
return_value = _readCoalesceExpr();
else if (MATCH("MINMAX", 6))
return_value = _readMinMaxExpr();
else if (MATCH("SQLVALUEFUNCTION", 16))
return_value = _readSQLValueFunction();
else if (MATCH("XMLEXPR", 7))
return_value = _readXmlExpr();
else if (MATCH("NULLTEST", 8))