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:
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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:
|
||||
|
@@ -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;
|
||||
|
@@ -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))
|
||||
|
Reference in New Issue
Block a user