#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
+#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/relation.h"
#include "utils/builtins.h"
break;
case T_ArrayRef:
{
- const ArrayRef *arrayref = (const ArrayRef *) expr;
+ const ArrayRef *arrayref = (const ArrayRef *) expr;
/* slice and/or store operations yield the array type */
if (arrayref->reflowerindexpr || arrayref->refassgnexpr)
break;
case T_SubLink:
{
- const SubLink *sublink = (const SubLink *) expr;
+ const SubLink *sublink = (const SubLink *) expr;
if (sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == ARRAY_SUBLINK)
break;
case T_SubPlan:
{
- const SubPlan *subplan = (const SubPlan *) expr;
+ const SubPlan *subplan = (const SubPlan *) expr;
if (subplan->subLinkType == EXPR_SUBLINK ||
subplan->subLinkType == ARRAY_SUBLINK)
break;
case T_SubLink:
{
- const SubLink *sublink = (const SubLink *) expr;
+ const SubLink *sublink = (const SubLink *) expr;
if (sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == ARRAY_SUBLINK)
break;
case T_SubPlan:
{
- const SubPlan *subplan = (const SubPlan *) expr;
+ const SubPlan *subplan = (const SubPlan *) expr;
if (subplan->subLinkType == EXPR_SUBLINK ||
subplan->subLinkType == ARRAY_SUBLINK)
* If all the alternatives agree on type/typmod, return that
* typmod, else use -1
*/
- const CaseExpr *cexpr = (const CaseExpr *) expr;
+ const CaseExpr *cexpr = (const CaseExpr *) expr;
Oid casetype = cexpr->casetype;
int32 typmod;
ListCell *arg;
* If all the elements agree on type/typmod, return that
* typmod, else use -1
*/
- const ArrayExpr *arrayexpr = (const ArrayExpr *) expr;
+ const ArrayExpr *arrayexpr = (const ArrayExpr *) expr;
Oid commontype;
int32 typmod;
ListCell *elem;
*/
if (expr && IsA(expr, FuncExpr))
{
- const FuncExpr *func = (const FuncExpr *) expr;
+ const FuncExpr *func = (const FuncExpr *) expr;
int nargs;
Const *second_arg;
return false;
}
+/*
+ * relabel_to_typmod
+ * Add a RelabelType node that changes just the typmod of the expression.
+ *
+ * This is primarily intended to be used during planning. Therefore, it
+ * strips any existing RelabelType nodes to maintain the planner's invariant
+ * that there are not adjacent RelabelTypes, and it uses COERCE_DONTCARE
+ * which would typically be inappropriate earlier.
+ */
+Node *
+relabel_to_typmod(Node *expr, int32 typmod)
+{
+ Oid type = exprType(expr);
+ Oid coll = exprCollation(expr);
+
+ /* Strip any existing RelabelType node(s) */
+ while (expr && IsA(expr, RelabelType))
+ expr = (Node *) ((RelabelType *) expr)->arg;
+
+ /* Apply new typmod, preserving the previous exposed type and collation */
+ return (Node *) makeRelabelType((Expr *) expr, type, typmod, coll,
+ COERCE_DONTCARE);
+}
+
/*
* expression_returns_set
* Test whether an expression returns a set result.
break;
case T_SubLink:
{
- const SubLink *sublink = (const SubLink *) expr;
+ const SubLink *sublink = (const SubLink *) expr;
if (sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == ARRAY_SUBLINK)
break;
case T_SubPlan:
{
- const SubPlan *subplan = (const SubPlan *) expr;
+ const SubPlan *subplan = (const SubPlan *) expr;
if (subplan->subLinkType == EXPR_SUBLINK ||
subplan->subLinkType == ARRAY_SUBLINK)
break;
case T_FuncExpr:
{
- const FuncExpr *fexpr = (const FuncExpr *) expr;
+ const FuncExpr *fexpr = (const FuncExpr *) expr;
/* consider both function name and leftmost arg */
loc = leftmostLoc(fexpr->location,
case T_DistinctExpr: /* struct-equivalent to OpExpr */
case T_NullIfExpr: /* struct-equivalent to OpExpr */
{
- const OpExpr *opexpr = (const OpExpr *) expr;
+ const OpExpr *opexpr = (const OpExpr *) expr;
/* consider both operator name and leftmost arg */
loc = leftmostLoc(opexpr->location,
break;
case T_BoolExpr:
{
- const BoolExpr *bexpr = (const BoolExpr *) expr;
+ const BoolExpr *bexpr = (const BoolExpr *) expr;
/*
* Same as above, to handle either NOT or AND/OR. We can't
break;
case T_SubLink:
{
- const SubLink *sublink = (const SubLink *) expr;
+ const SubLink *sublink = (const SubLink *) expr;
/* check the testexpr, if any, and the operator/keyword */
loc = leftmostLoc(exprLocation(sublink->testexpr),
break;
case T_XmlExpr:
{
- const XmlExpr *xexpr = (const XmlExpr *) expr;
+ const XmlExpr *xexpr = (const XmlExpr *) expr;
/* consider both function name and leftmost arg */
loc = leftmostLoc(xexpr->location,
break;
case T_A_Expr:
{
- const A_Expr *aexpr = (const A_Expr *) expr;
+ const A_Expr *aexpr = (const A_Expr *) expr;
/* use leftmost of operator or left operand (if any) */
/* we assume right operand can't be to left of operator */
break;
case T_FuncCall:
{
- const FuncCall *fc = (const FuncCall *) expr;
+ const FuncCall *fc = (const FuncCall *) expr;
/* consider both function name and leftmost arg */
/* (we assume any ORDER BY nodes must be to right of name) */
break;
case T_TypeCast:
{
- const TypeCast *tc = (const TypeCast *) expr;
+ const TypeCast *tc = (const TypeCast *) expr;
/*
* This could represent CAST(), ::, or TypeName 'literal', so
* that could appear under it, but not other statement types.
*/
bool
- raw_expression_tree_walker(Node *node, bool (*walker) (), void *context)
+raw_expression_tree_walker(Node *node,
+ bool (*walker) (),
+ void *context)
{
ListCell *temp;