#include "postgres.h"
#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"
#include "utils/lsyscache.h"
Go to the source code of this file.
Defines | |
#define | FLATCOPY(newnode, node, nodetype) |
#define | CHECKFLATCOPY(newnode, node, nodetype) |
#define | MUTATE(newfield, oldfield, fieldtype) ( (newfield) = (fieldtype) mutator((Node *) (oldfield), context) ) |
Functions | |
static bool | expression_returns_set_walker (Node *node, void *context) |
static int | leftmostLoc (int loc1, int loc2) |
Oid | exprType (const Node *expr) |
int32 | exprTypmod (const Node *expr) |
bool | exprIsLengthCoercion (const Node *expr, int32 *coercedTypmod) |
Node * | relabel_to_typmod (Node *expr, int32 typmod) |
bool | expression_returns_set (Node *clause) |
Oid | exprCollation (const Node *expr) |
Oid | exprInputCollation (const Node *expr) |
void | exprSetCollation (Node *expr, Oid collation) |
void | exprSetInputCollation (Node *expr, Oid inputcollation) |
int | exprLocation (const Node *expr) |
bool | expression_tree_walker (Node *node, bool(*walker)(), void *context) |
bool | query_tree_walker (Query *query, bool(*walker)(), void *context, int flags) |
bool | range_table_walker (List *rtable, bool(*walker)(), void *context, int flags) |
Node * | expression_tree_mutator (Node *node, Node *(*mutator)(), void *context) |
Query * | query_tree_mutator (Query *query, Node *(*mutator)(), void *context, int flags) |
List * | range_table_mutator (List *rtable, Node *(*mutator)(), void *context, int flags) |
bool | query_or_expression_tree_walker (Node *node, bool(*walker)(), void *context, int flags) |
Node * | query_or_expression_tree_mutator (Node *node, Node *(*mutator)(), void *context, int flags) |
bool | raw_expression_tree_walker (Node *node, bool(*walker)(), void *context) |
#define CHECKFLATCOPY | ( | newnode, | ||
node, | ||||
nodetype | ||||
) |
( AssertMacro(IsA((node), nodetype)), \ (newnode) = (nodetype *) palloc(sizeof(nodetype)), \ memcpy((newnode), (node), sizeof(nodetype)) )
Referenced by range_table_mutator().
#define FLATCOPY | ( | newnode, | ||
node, | ||||
nodetype | ||||
) |
( (newnode) = (nodetype *) palloc(sizeof(nodetype)), \ memcpy((newnode), (node), sizeof(nodetype)) )
Referenced by expression_tree_mutator(), query_tree_mutator(), and range_table_mutator().
#define MUTATE | ( | newfield, | ||
oldfield, | ||||
fieldtype | ||||
) | ( (newfield) = (fieldtype) mutator((Node *) (oldfield), context) ) |
Referenced by expression_tree_mutator(), query_tree_mutator(), and range_table_mutator().
Definition at line 659 of file nodeFuncs.c.
References arg, ARRAY_SUBLINK, Assert, elog, ERROR, EXPR_SUBLINK, exprCollation(), SubPlan::firstColCollation, IS_XMLSERIALIZE, IsA, linitial, nodeTag, SubPlan::subLinkType, SubLink::subLinkType, AlternativeSubPlan::subplans, SubLink::subselect, T_Aggref, T_AlternativeSubPlan, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_CollateExpr, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_MinMaxExpr, T_NamedArgExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_PlaceHolderVar, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SetToDefault, T_SubLink, T_SubPlan, T_Var, T_WindowFunc, T_XmlExpr, and Query::targetList.
Referenced by analyzeCTE(), analyzeCTETargetList(), assign_collations_walker(), assign_nestloop_param_placeholdervar(), build_subplan(), canonicalize_ec_expression(), ComputeIndexAttrs(), convert_EXISTS_to_ANY(), DefineVirtualRelation(), eval_const_expressions_mutator(), ExecInitAgg(), ExecInitFunctionScan(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), expandRecordVariable(), expandRTE(), exprCollation(), exprSetCollation(), fix_indexqual_operand(), generate_setop_tlist(), generate_subquery_params(), get_first_col_type(), get_rte_attribute_type(), inline_function(), make_agg_subplan(), make_pathkey_from_sortop(), make_sort_from_groupcols(), make_sort_from_sortclauses(), makeVarFromTargetEntry(), makeWholeRowVar(), pg_get_indexdef_worker(), relabel_to_typmod(), replace_outer_placeholdervar(), scalararraysel(), set_dummy_tlist_references(), tlist_same_collations(), transformCaseExpr(), and transformSubLink().
{ Oid coll; if (!expr) return InvalidOid; switch (nodeTag(expr)) { case T_Var: coll = ((const Var *) expr)->varcollid; break; case T_Const: coll = ((const Const *) expr)->constcollid; break; case T_Param: coll = ((const Param *) expr)->paramcollid; break; case T_Aggref: coll = ((const Aggref *) expr)->aggcollid; break; case T_WindowFunc: coll = ((const WindowFunc *) expr)->wincollid; break; case T_ArrayRef: coll = ((const ArrayRef *) expr)->refcollid; break; case T_FuncExpr: coll = ((const FuncExpr *) expr)->funccollid; break; case T_NamedArgExpr: coll = exprCollation((Node *) ((const NamedArgExpr *) expr)->arg); break; case T_OpExpr: coll = ((const OpExpr *) expr)->opcollid; break; case T_DistinctExpr: coll = ((const DistinctExpr *) expr)->opcollid; break; case T_NullIfExpr: coll = ((const NullIfExpr *) expr)->opcollid; break; case T_ScalarArrayOpExpr: coll = InvalidOid; /* result is always boolean */ break; case T_BoolExpr: coll = InvalidOid; /* result is always boolean */ break; case T_SubLink: { const SubLink *sublink = (const SubLink *) expr; if (sublink->subLinkType == EXPR_SUBLINK || sublink->subLinkType == ARRAY_SUBLINK) { /* get the collation of subselect's first target column */ Query *qtree = (Query *) sublink->subselect; TargetEntry *tent; if (!qtree || !IsA(qtree, Query)) elog(ERROR, "cannot get collation for untransformed sublink"); tent = (TargetEntry *) linitial(qtree->targetList); Assert(IsA(tent, TargetEntry)); Assert(!tent->resjunk); coll = exprCollation((Node *) tent->expr); /* collation doesn't change if it's converted to array */ } else { /* for all other sublink types, result is boolean */ coll = InvalidOid; } } break; case T_SubPlan: { const SubPlan *subplan = (const SubPlan *) expr; if (subplan->subLinkType == EXPR_SUBLINK || subplan->subLinkType == ARRAY_SUBLINK) { /* get the collation of subselect's first target column */ coll = subplan->firstColCollation; /* collation doesn't change if it's converted to array */ } else { /* for all other subplan types, result is boolean */ coll = InvalidOid; } } break; case T_AlternativeSubPlan: { const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr; /* subplans should all return the same thing */ coll = exprCollation((Node *) linitial(asplan->subplans)); } break; case T_FieldSelect: coll = ((const FieldSelect *) expr)->resultcollid; break; case T_FieldStore: coll = InvalidOid; /* result is always composite */ break; case T_RelabelType: coll = ((const RelabelType *) expr)->resultcollid; break; case T_CoerceViaIO: coll = ((const CoerceViaIO *) expr)->resultcollid; break; case T_ArrayCoerceExpr: coll = ((const ArrayCoerceExpr *) expr)->resultcollid; break; case T_ConvertRowtypeExpr: coll = InvalidOid; /* result is always composite */ break; case T_CollateExpr: coll = ((const CollateExpr *) expr)->collOid; break; case T_CaseExpr: coll = ((const CaseExpr *) expr)->casecollid; break; case T_CaseTestExpr: coll = ((const CaseTestExpr *) expr)->collation; break; case T_ArrayExpr: coll = ((const ArrayExpr *) expr)->array_collid; break; case T_RowExpr: coll = InvalidOid; /* result is always composite */ break; case T_RowCompareExpr: coll = InvalidOid; /* result is always boolean */ break; case T_CoalesceExpr: coll = ((const CoalesceExpr *) expr)->coalescecollid; break; case T_MinMaxExpr: coll = ((const MinMaxExpr *) expr)->minmaxcollid; break; case T_XmlExpr: /* * XMLSERIALIZE returns text from non-collatable inputs, so its * collation is always default. The other cases return boolean or * XML, which are non-collatable. */ if (((const XmlExpr *) expr)->op == IS_XMLSERIALIZE) coll = DEFAULT_COLLATION_OID; else coll = InvalidOid; break; case T_NullTest: coll = InvalidOid; /* result is always boolean */ break; case T_BooleanTest: coll = InvalidOid; /* result is always boolean */ break; case T_CoerceToDomain: coll = ((const CoerceToDomain *) expr)->resultcollid; break; case T_CoerceToDomainValue: coll = ((const CoerceToDomainValue *) expr)->collation; break; case T_SetToDefault: coll = ((const SetToDefault *) expr)->collation; break; case T_CurrentOfExpr: coll = InvalidOid; /* result is always boolean */ break; case T_PlaceHolderVar: coll = exprCollation((Node *) ((const PlaceHolderVar *) expr)->phexpr); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); coll = InvalidOid; /* keep compiler quiet */ break; } return coll; }
Definition at line 583 of file nodeFuncs.c.
References expression_returns_set_walker(), and NULL.
Referenced by ATPrepAlterColumnType(), CheckSelectLocking(), coerce_to_boolean(), coerce_to_specific_type(), cookDefault(), get_eclass_for_sort_expr(), inline_function(), is_simple_subquery(), make_row_comparison_op(), pass_down_bound(), qual_is_pushdown_safe(), simplify_EXISTS_query(), TargetListSupportsBackwardScan(), and transformIndexStmt().
{ return expression_returns_set_walker(clause, NULL); }
Definition at line 589 of file nodeFuncs.c.
References expression_tree_walker(), FuncExpr::funcretset, IsA, NULL, and OpExpr::opretset.
Referenced by expression_returns_set().
{ if (node == NULL) return false; if (IsA(node, FuncExpr)) { FuncExpr *expr = (FuncExpr *) node; if (expr->funcretset) return true; /* else fall through to check args */ } if (IsA(node, OpExpr)) { OpExpr *expr = (OpExpr *) node; if (expr->opretset) return true; /* else fall through to check args */ } /* Avoid recursion for some cases that can't return a set */ if (IsA(node, Aggref)) return false; if (IsA(node, WindowFunc)) return false; if (IsA(node, DistinctExpr)) return false; if (IsA(node, NullIfExpr)) return false; if (IsA(node, ScalarArrayOpExpr)) return false; if (IsA(node, BoolExpr)) return false; if (IsA(node, SubLink)) return false; if (IsA(node, SubPlan)) return false; if (IsA(node, AlternativeSubPlan)) return false; if (IsA(node, ArrayExpr)) return false; if (IsA(node, RowExpr)) return false; if (IsA(node, RowCompareExpr)) return false; if (IsA(node, CoalesceExpr)) return false; if (IsA(node, MinMaxExpr)) return false; if (IsA(node, XmlExpr)) return false; return expression_tree_walker(node, expression_returns_set_walker, context); }
Definition at line 2012 of file nodeFuncs.c.
References Aggref::aggdistinct, Aggref::aggorder, CoerceToDomain::arg, BooleanTest::arg, NullTest::arg, CaseExpr::arg, CollateExpr::arg, ConvertRowtypeExpr::arg, ArrayCoerceExpr::arg, CoerceViaIO::arg, RelabelType::arg, FieldStore::arg, FieldSelect::arg, NamedArgExpr::arg, XmlExpr::args, MinMaxExpr::args, CoalesceExpr::args, RowExpr::args, CaseExpr::args, SubPlan::args, BoolExpr::args, ScalarArrayOpExpr::args, OpExpr::args, FuncExpr::args, WindowFunc::args, Aggref::args, check_stack_depth(), copyObject(), CommonTableExpr::ctequery, CaseExpr::defresult, ArrayExpr::elements, elog, WindowClause::endOffset, ERROR, TargetEntry::expr, CaseWhen::expr, FieldStore::fieldnums, FLATCOPY, FromExpr::fromlist, lappend(), SetOperationStmt::larg, JoinExpr::larg, RowCompareExpr::largs, lfirst, list_copy(), MUTATE, XmlExpr::named_args, FieldStore::newvals, nodeTag, NULL, WindowClause::orderClause, WindowClause::partitionClause, PlaceHolderInfo::ph_var, PlaceHolderVar::phexpr, JoinExpr::quals, FromExpr::quals, SetOperationStmt::rarg, JoinExpr::rarg, RowCompareExpr::rargs, ArrayRef::refassgnexpr, ArrayRef::refexpr, ArrayRef::reflowerindexpr, ArrayRef::refupperindexpr, CaseWhen::result, WindowClause::startOffset, AlternativeSubPlan::subplans, SubLink::subselect, T_Aggref, T_AlternativeSubPlan, T_AppendRelInfo, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CaseWhen, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_CollateExpr, T_CommonTableExpr, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FromExpr, T_FuncExpr, T_JoinExpr, T_List, T_MinMaxExpr, T_NamedArgExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_PlaceHolderInfo, T_PlaceHolderVar, T_Query, T_RangeTblRef, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SetOperationStmt, T_SetToDefault, T_SortGroupClause, T_SubLink, T_SubPlan, T_TargetEntry, T_Var, T_WindowClause, T_WindowFunc, T_XmlExpr, SubPlan::testexpr, SubLink::testexpr, and AppendRelInfo::translated_vars.
Referenced by adjust_appendrel_attrs_mutator(), convert_testexpr_mutator(), eval_const_expressions_mutator(), fix_join_expr_mutator(), fix_scan_expr_mutator(), fix_upper_expr_mutator(), flatten_join_alias_vars_mutator(), map_variable_attnos_mutator(), process_sublinks_mutator(), replace_aggs_with_params_mutator(), replace_correlation_vars_mutator(), replace_nestloop_params_mutator(), replace_rte_variables_mutator(), simplify_function(), substitute_actual_parameters_mutator(), and substitute_actual_srf_parameters_mutator().
{ /* * The mutator has already decided not to modify the current node, but we * must call the mutator for any sub-nodes. */ #define FLATCOPY(newnode, node, nodetype) \ ( (newnode) = (nodetype *) palloc(sizeof(nodetype)), \ memcpy((newnode), (node), sizeof(nodetype)) ) #define CHECKFLATCOPY(newnode, node, nodetype) \ ( AssertMacro(IsA((node), nodetype)), \ (newnode) = (nodetype *) palloc(sizeof(nodetype)), \ memcpy((newnode), (node), sizeof(nodetype)) ) #define MUTATE(newfield, oldfield, fieldtype) \ ( (newfield) = (fieldtype) mutator((Node *) (oldfield), context) ) if (node == NULL) return NULL; /* Guard against stack overflow due to overly complex expressions */ check_stack_depth(); switch (nodeTag(node)) { /* * Primitive node types with no expression subnodes. Var and * Const are frequent enough to deserve special cases, the others * we just use copyObject for. */ case T_Var: { Var *var = (Var *) node; Var *newnode; FLATCOPY(newnode, var, Var); return (Node *) newnode; } break; case T_Const: { Const *oldnode = (Const *) node; Const *newnode; FLATCOPY(newnode, oldnode, Const); /* XXX we don't bother with datumCopy; should we? */ return (Node *) newnode; } break; case T_Param: case T_CoerceToDomainValue: case T_CaseTestExpr: case T_SetToDefault: case T_CurrentOfExpr: case T_RangeTblRef: case T_SortGroupClause: return (Node *) copyObject(node); case T_Aggref: { Aggref *aggref = (Aggref *) node; Aggref *newnode; FLATCOPY(newnode, aggref, Aggref); MUTATE(newnode->args, aggref->args, List *); MUTATE(newnode->aggorder, aggref->aggorder, List *); MUTATE(newnode->aggdistinct, aggref->aggdistinct, List *); return (Node *) newnode; } break; case T_WindowFunc: { WindowFunc *wfunc = (WindowFunc *) node; WindowFunc *newnode; FLATCOPY(newnode, wfunc, WindowFunc); MUTATE(newnode->args, wfunc->args, List *); return (Node *) newnode; } break; case T_ArrayRef: { ArrayRef *arrayref = (ArrayRef *) node; ArrayRef *newnode; FLATCOPY(newnode, arrayref, ArrayRef); MUTATE(newnode->refupperindexpr, arrayref->refupperindexpr, List *); MUTATE(newnode->reflowerindexpr, arrayref->reflowerindexpr, List *); MUTATE(newnode->refexpr, arrayref->refexpr, Expr *); MUTATE(newnode->refassgnexpr, arrayref->refassgnexpr, Expr *); return (Node *) newnode; } break; case T_FuncExpr: { FuncExpr *expr = (FuncExpr *) node; FuncExpr *newnode; FLATCOPY(newnode, expr, FuncExpr); MUTATE(newnode->args, expr->args, List *); return (Node *) newnode; } break; case T_NamedArgExpr: { NamedArgExpr *nexpr = (NamedArgExpr *) node; NamedArgExpr *newnode; FLATCOPY(newnode, nexpr, NamedArgExpr); MUTATE(newnode->arg, nexpr->arg, Expr *); return (Node *) newnode; } break; case T_OpExpr: { OpExpr *expr = (OpExpr *) node; OpExpr *newnode; FLATCOPY(newnode, expr, OpExpr); MUTATE(newnode->args, expr->args, List *); return (Node *) newnode; } break; case T_DistinctExpr: { DistinctExpr *expr = (DistinctExpr *) node; DistinctExpr *newnode; FLATCOPY(newnode, expr, DistinctExpr); MUTATE(newnode->args, expr->args, List *); return (Node *) newnode; } break; case T_NullIfExpr: { NullIfExpr *expr = (NullIfExpr *) node; NullIfExpr *newnode; FLATCOPY(newnode, expr, NullIfExpr); MUTATE(newnode->args, expr->args, List *); return (Node *) newnode; } break; case T_ScalarArrayOpExpr: { ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; ScalarArrayOpExpr *newnode; FLATCOPY(newnode, expr, ScalarArrayOpExpr); MUTATE(newnode->args, expr->args, List *); return (Node *) newnode; } break; case T_BoolExpr: { BoolExpr *expr = (BoolExpr *) node; BoolExpr *newnode; FLATCOPY(newnode, expr, BoolExpr); MUTATE(newnode->args, expr->args, List *); return (Node *) newnode; } break; case T_SubLink: { SubLink *sublink = (SubLink *) node; SubLink *newnode; FLATCOPY(newnode, sublink, SubLink); MUTATE(newnode->testexpr, sublink->testexpr, Node *); /* * Also invoke the mutator on the sublink's Query node, so it * can recurse into the sub-query if it wants to. */ MUTATE(newnode->subselect, sublink->subselect, Node *); return (Node *) newnode; } break; case T_SubPlan: { SubPlan *subplan = (SubPlan *) node; SubPlan *newnode; FLATCOPY(newnode, subplan, SubPlan); /* transform testexpr */ MUTATE(newnode->testexpr, subplan->testexpr, Node *); /* transform args list (params to be passed to subplan) */ MUTATE(newnode->args, subplan->args, List *); /* but not the sub-Plan itself, which is referenced as-is */ return (Node *) newnode; } break; case T_AlternativeSubPlan: { AlternativeSubPlan *asplan = (AlternativeSubPlan *) node; AlternativeSubPlan *newnode; FLATCOPY(newnode, asplan, AlternativeSubPlan); MUTATE(newnode->subplans, asplan->subplans, List *); return (Node *) newnode; } break; case T_FieldSelect: { FieldSelect *fselect = (FieldSelect *) node; FieldSelect *newnode; FLATCOPY(newnode, fselect, FieldSelect); MUTATE(newnode->arg, fselect->arg, Expr *); return (Node *) newnode; } break; case T_FieldStore: { FieldStore *fstore = (FieldStore *) node; FieldStore *newnode; FLATCOPY(newnode, fstore, FieldStore); MUTATE(newnode->arg, fstore->arg, Expr *); MUTATE(newnode->newvals, fstore->newvals, List *); newnode->fieldnums = list_copy(fstore->fieldnums); return (Node *) newnode; } break; case T_RelabelType: { RelabelType *relabel = (RelabelType *) node; RelabelType *newnode; FLATCOPY(newnode, relabel, RelabelType); MUTATE(newnode->arg, relabel->arg, Expr *); return (Node *) newnode; } break; case T_CoerceViaIO: { CoerceViaIO *iocoerce = (CoerceViaIO *) node; CoerceViaIO *newnode; FLATCOPY(newnode, iocoerce, CoerceViaIO); MUTATE(newnode->arg, iocoerce->arg, Expr *); return (Node *) newnode; } break; case T_ArrayCoerceExpr: { ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; ArrayCoerceExpr *newnode; FLATCOPY(newnode, acoerce, ArrayCoerceExpr); MUTATE(newnode->arg, acoerce->arg, Expr *); return (Node *) newnode; } break; case T_ConvertRowtypeExpr: { ConvertRowtypeExpr *convexpr = (ConvertRowtypeExpr *) node; ConvertRowtypeExpr *newnode; FLATCOPY(newnode, convexpr, ConvertRowtypeExpr); MUTATE(newnode->arg, convexpr->arg, Expr *); return (Node *) newnode; } break; case T_CollateExpr: { CollateExpr *collate = (CollateExpr *) node; CollateExpr *newnode; FLATCOPY(newnode, collate, CollateExpr); MUTATE(newnode->arg, collate->arg, Expr *); return (Node *) newnode; } break; case T_CaseExpr: { CaseExpr *caseexpr = (CaseExpr *) node; CaseExpr *newnode; FLATCOPY(newnode, caseexpr, CaseExpr); MUTATE(newnode->arg, caseexpr->arg, Expr *); MUTATE(newnode->args, caseexpr->args, List *); MUTATE(newnode->defresult, caseexpr->defresult, Expr *); return (Node *) newnode; } break; case T_CaseWhen: { CaseWhen *casewhen = (CaseWhen *) node; CaseWhen *newnode; FLATCOPY(newnode, casewhen, CaseWhen); MUTATE(newnode->expr, casewhen->expr, Expr *); MUTATE(newnode->result, casewhen->result, Expr *); return (Node *) newnode; } break; case T_ArrayExpr: { ArrayExpr *arrayexpr = (ArrayExpr *) node; ArrayExpr *newnode; FLATCOPY(newnode, arrayexpr, ArrayExpr); MUTATE(newnode->elements, arrayexpr->elements, List *); return (Node *) newnode; } break; case T_RowExpr: { RowExpr *rowexpr = (RowExpr *) node; RowExpr *newnode; FLATCOPY(newnode, rowexpr, RowExpr); MUTATE(newnode->args, rowexpr->args, List *); /* Assume colnames needn't be duplicated */ return (Node *) newnode; } break; case T_RowCompareExpr: { RowCompareExpr *rcexpr = (RowCompareExpr *) node; RowCompareExpr *newnode; FLATCOPY(newnode, rcexpr, RowCompareExpr); MUTATE(newnode->largs, rcexpr->largs, List *); MUTATE(newnode->rargs, rcexpr->rargs, List *); return (Node *) newnode; } break; case T_CoalesceExpr: { CoalesceExpr *coalesceexpr = (CoalesceExpr *) node; CoalesceExpr *newnode; FLATCOPY(newnode, coalesceexpr, CoalesceExpr); MUTATE(newnode->args, coalesceexpr->args, List *); return (Node *) newnode; } break; case T_MinMaxExpr: { MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; MinMaxExpr *newnode; FLATCOPY(newnode, minmaxexpr, MinMaxExpr); MUTATE(newnode->args, minmaxexpr->args, List *); return (Node *) newnode; } break; case T_XmlExpr: { XmlExpr *xexpr = (XmlExpr *) node; XmlExpr *newnode; FLATCOPY(newnode, xexpr, XmlExpr); MUTATE(newnode->named_args, xexpr->named_args, List *); /* assume mutator does not care about arg_names */ MUTATE(newnode->args, xexpr->args, List *); return (Node *) newnode; } break; case T_NullTest: { NullTest *ntest = (NullTest *) node; NullTest *newnode; FLATCOPY(newnode, ntest, NullTest); MUTATE(newnode->arg, ntest->arg, Expr *); return (Node *) newnode; } break; case T_BooleanTest: { BooleanTest *btest = (BooleanTest *) node; BooleanTest *newnode; FLATCOPY(newnode, btest, BooleanTest); MUTATE(newnode->arg, btest->arg, Expr *); return (Node *) newnode; } break; case T_CoerceToDomain: { CoerceToDomain *ctest = (CoerceToDomain *) node; CoerceToDomain *newnode; FLATCOPY(newnode, ctest, CoerceToDomain); MUTATE(newnode->arg, ctest->arg, Expr *); return (Node *) newnode; } break; case T_TargetEntry: { TargetEntry *targetentry = (TargetEntry *) node; TargetEntry *newnode; FLATCOPY(newnode, targetentry, TargetEntry); MUTATE(newnode->expr, targetentry->expr, Expr *); return (Node *) newnode; } break; case T_Query: /* Do nothing with a sub-Query, per discussion above */ return node; case T_WindowClause: { WindowClause *wc = (WindowClause *) node; WindowClause *newnode; FLATCOPY(newnode, wc, WindowClause); MUTATE(newnode->partitionClause, wc->partitionClause, List *); MUTATE(newnode->orderClause, wc->orderClause, List *); MUTATE(newnode->startOffset, wc->startOffset, Node *); MUTATE(newnode->endOffset, wc->endOffset, Node *); return (Node *) newnode; } break; case T_CommonTableExpr: { CommonTableExpr *cte = (CommonTableExpr *) node; CommonTableExpr *newnode; FLATCOPY(newnode, cte, CommonTableExpr); /* * Also invoke the mutator on the CTE's Query node, so it can * recurse into the sub-query if it wants to. */ MUTATE(newnode->ctequery, cte->ctequery, Node *); return (Node *) newnode; } break; case T_List: { /* * We assume the mutator isn't interested in the list nodes * per se, so just invoke it on each list element. NOTE: this * would fail badly on a list with integer elements! */ List *resultlist; ListCell *temp; resultlist = NIL; foreach(temp, (List *) node) { resultlist = lappend(resultlist, mutator((Node *) lfirst(temp), context)); } return (Node *) resultlist; } break; case T_FromExpr: { FromExpr *from = (FromExpr *) node; FromExpr *newnode; FLATCOPY(newnode, from, FromExpr); MUTATE(newnode->fromlist, from->fromlist, List *); MUTATE(newnode->quals, from->quals, Node *); return (Node *) newnode; } break; case T_JoinExpr: { JoinExpr *join = (JoinExpr *) node; JoinExpr *newnode; FLATCOPY(newnode, join, JoinExpr); MUTATE(newnode->larg, join->larg, Node *); MUTATE(newnode->rarg, join->rarg, Node *); MUTATE(newnode->quals, join->quals, Node *); /* We do not mutate alias or using by default */ return (Node *) newnode; } break; case T_SetOperationStmt: { SetOperationStmt *setop = (SetOperationStmt *) node; SetOperationStmt *newnode; FLATCOPY(newnode, setop, SetOperationStmt); MUTATE(newnode->larg, setop->larg, Node *); MUTATE(newnode->rarg, setop->rarg, Node *); /* We do not mutate groupClauses by default */ return (Node *) newnode; } break; case T_PlaceHolderVar: { PlaceHolderVar *phv = (PlaceHolderVar *) node; PlaceHolderVar *newnode; FLATCOPY(newnode, phv, PlaceHolderVar); MUTATE(newnode->phexpr, phv->phexpr, Expr *); /* Assume we need not copy the relids bitmapset */ return (Node *) newnode; } break; case T_AppendRelInfo: { AppendRelInfo *appinfo = (AppendRelInfo *) node; AppendRelInfo *newnode; FLATCOPY(newnode, appinfo, AppendRelInfo); MUTATE(newnode->translated_vars, appinfo->translated_vars, List *); return (Node *) newnode; } break; case T_PlaceHolderInfo: { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node; PlaceHolderInfo *newnode; FLATCOPY(newnode, phinfo, PlaceHolderInfo); MUTATE(newnode->ph_var, phinfo->ph_var, PlaceHolderVar *); /* Assume we need not copy the relids bitmapsets */ return (Node *) newnode; } break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); break; } /* can't get here, but keep compiler happy */ return NULL; }
Definition at line 1526 of file nodeFuncs.c.
References Aggref::aggdistinct, Aggref::aggorder, CaseExpr::arg, FieldStore::arg, arg, XmlExpr::args, CaseExpr::args, SubPlan::args, BoolExpr::args, ScalarArrayOpExpr::args, OpExpr::args, FuncExpr::args, WindowFunc::args, Aggref::args, Assert, check_stack_depth(), CommonTableExpr::ctequery, CaseExpr::defresult, elog, WindowClause::endOffset, ERROR, CaseWhen::expr, expression_tree_walker(), FromExpr::fromlist, IsA, SetOperationStmt::larg, JoinExpr::larg, RowCompareExpr::largs, lfirst, XmlExpr::named_args, FieldStore::newvals, nodeTag, NULL, WindowClause::orderClause, WindowClause::partitionClause, JoinExpr::quals, FromExpr::quals, SetOperationStmt::rarg, JoinExpr::rarg, RowCompareExpr::rargs, ArrayRef::refassgnexpr, ArrayRef::refexpr, ArrayRef::reflowerindexpr, ArrayRef::refupperindexpr, CaseWhen::result, WindowClause::startOffset, SubLink::subselect, T_Aggref, T_AlternativeSubPlan, T_AppendRelInfo, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_CollateExpr, T_CommonTableExpr, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FromExpr, T_FuncExpr, T_JoinExpr, T_List, T_MinMaxExpr, T_NamedArgExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_PlaceHolderInfo, T_PlaceHolderVar, T_Query, T_RangeTblRef, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SetOperationStmt, T_SetToDefault, T_SortGroupClause, T_SubLink, T_SubPlan, T_TargetEntry, T_Var, T_WindowClause, T_WindowFunc, T_XmlExpr, SubPlan::testexpr, SubLink::testexpr, and AppendRelInfo::translated_vars.
Referenced by acquireLocksOnSubLinks(), assign_collations_walker(), attribute_used_walker(), ChangeVarNodes_walker(), check_agg_arguments(), check_agg_arguments_walker(), check_parameter_resolution_walker(), check_ungrouped_columns_walker(), checkExprHasSubLink_walker(), contain_agg_clause_walker(), contain_aggs_of_level_walker(), contain_leaky_functions_walker(), contain_mutable_functions_walker(), contain_nonstrict_functions_walker(), contain_subplans_walker(), contain_var_clause_walker(), contain_vars_of_level_walker(), contain_volatile_functions_walker(), contain_windowfuncs_walker(), cost_qual_eval_walker(), count_agg_clauses_walker(), expression_returns_set_rows_walker(), expression_returns_set_walker(), expression_tree_walker(), extract_query_dependencies_walker(), finalize_primnode(), find_expr_references_walker(), find_minmax_aggs_walker(), find_unaggregated_cols_walker(), find_window_functions_walker(), fireRIRonSubLink(), fix_opfuncids_walker(), fix_scan_expr_walker(), get_last_attnums(), IncrementVarSublevelsUp_walker(), isQueryUsingTempRelation_walker(), locate_agg_of_level_walker(), locate_var_of_level_walker(), locate_windowfunc_walker(), OffsetVarNodes_walker(), pull_var_clause_walker(), pull_varattnos_walker(), pull_varnos_walker(), pull_vars_walker(), query_contains_extern_params_walker(), rangeTableEntry_used_walker(), ScanQueryWalker(), setRuleCheckAsUser_walker(), and substitute_multiple_relids_walker().
{ ListCell *temp; /* * The walker has already visited the current node, and so we need only * recurse into any sub-nodes it has. * * We assume that the walker is not interested in List nodes per se, so * when we expect a List we just recurse directly to self without * bothering to call the walker. */ if (node == NULL) return false; /* Guard against stack overflow due to overly complex expressions */ check_stack_depth(); switch (nodeTag(node)) { case T_Var: case T_Const: case T_Param: case T_CoerceToDomainValue: case T_CaseTestExpr: case T_SetToDefault: case T_CurrentOfExpr: case T_RangeTblRef: case T_SortGroupClause: /* primitive node types with no expression subnodes */ break; case T_Aggref: { Aggref *expr = (Aggref *) node; /* recurse directly on List */ if (expression_tree_walker((Node *) expr->args, walker, context)) return true; if (expression_tree_walker((Node *) expr->aggorder, walker, context)) return true; if (expression_tree_walker((Node *) expr->aggdistinct, walker, context)) return true; } break; case T_WindowFunc: { WindowFunc *expr = (WindowFunc *) node; /* recurse directly on List */ if (expression_tree_walker((Node *) expr->args, walker, context)) return true; } break; case T_ArrayRef: { ArrayRef *aref = (ArrayRef *) node; /* recurse directly for upper/lower array index lists */ if (expression_tree_walker((Node *) aref->refupperindexpr, walker, context)) return true; if (expression_tree_walker((Node *) aref->reflowerindexpr, walker, context)) return true; /* walker must see the refexpr and refassgnexpr, however */ if (walker(aref->refexpr, context)) return true; if (walker(aref->refassgnexpr, context)) return true; } break; case T_FuncExpr: { FuncExpr *expr = (FuncExpr *) node; if (expression_tree_walker((Node *) expr->args, walker, context)) return true; } break; case T_NamedArgExpr: return walker(((NamedArgExpr *) node)->arg, context); case T_OpExpr: case T_DistinctExpr: /* struct-equivalent to OpExpr */ case T_NullIfExpr: /* struct-equivalent to OpExpr */ { OpExpr *expr = (OpExpr *) node; if (expression_tree_walker((Node *) expr->args, walker, context)) return true; } break; case T_ScalarArrayOpExpr: { ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; if (expression_tree_walker((Node *) expr->args, walker, context)) return true; } break; case T_BoolExpr: { BoolExpr *expr = (BoolExpr *) node; if (expression_tree_walker((Node *) expr->args, walker, context)) return true; } break; case T_SubLink: { SubLink *sublink = (SubLink *) node; if (walker(sublink->testexpr, context)) return true; /* * Also invoke the walker on the sublink's Query node, so it * can recurse into the sub-query if it wants to. */ return walker(sublink->subselect, context); } break; case T_SubPlan: { SubPlan *subplan = (SubPlan *) node; /* recurse into the testexpr, but not into the Plan */ if (walker(subplan->testexpr, context)) return true; /* also examine args list */ if (expression_tree_walker((Node *) subplan->args, walker, context)) return true; } break; case T_AlternativeSubPlan: return walker(((AlternativeSubPlan *) node)->subplans, context); case T_FieldSelect: return walker(((FieldSelect *) node)->arg, context); case T_FieldStore: { FieldStore *fstore = (FieldStore *) node; if (walker(fstore->arg, context)) return true; if (walker(fstore->newvals, context)) return true; } break; case T_RelabelType: return walker(((RelabelType *) node)->arg, context); case T_CoerceViaIO: return walker(((CoerceViaIO *) node)->arg, context); case T_ArrayCoerceExpr: return walker(((ArrayCoerceExpr *) node)->arg, context); case T_ConvertRowtypeExpr: return walker(((ConvertRowtypeExpr *) node)->arg, context); case T_CollateExpr: return walker(((CollateExpr *) node)->arg, context); case T_CaseExpr: { CaseExpr *caseexpr = (CaseExpr *) node; if (walker(caseexpr->arg, context)) return true; /* we assume walker doesn't care about CaseWhens, either */ foreach(temp, caseexpr->args) { CaseWhen *when = (CaseWhen *) lfirst(temp); Assert(IsA(when, CaseWhen)); if (walker(when->expr, context)) return true; if (walker(when->result, context)) return true; } if (walker(caseexpr->defresult, context)) return true; } break; case T_ArrayExpr: return walker(((ArrayExpr *) node)->elements, context); case T_RowExpr: /* Assume colnames isn't interesting */ return walker(((RowExpr *) node)->args, context); case T_RowCompareExpr: { RowCompareExpr *rcexpr = (RowCompareExpr *) node; if (walker(rcexpr->largs, context)) return true; if (walker(rcexpr->rargs, context)) return true; } break; case T_CoalesceExpr: return walker(((CoalesceExpr *) node)->args, context); case T_MinMaxExpr: return walker(((MinMaxExpr *) node)->args, context); case T_XmlExpr: { XmlExpr *xexpr = (XmlExpr *) node; if (walker(xexpr->named_args, context)) return true; /* we assume walker doesn't care about arg_names */ if (walker(xexpr->args, context)) return true; } break; case T_NullTest: return walker(((NullTest *) node)->arg, context); case T_BooleanTest: return walker(((BooleanTest *) node)->arg, context); case T_CoerceToDomain: return walker(((CoerceToDomain *) node)->arg, context); case T_TargetEntry: return walker(((TargetEntry *) node)->expr, context); case T_Query: /* Do nothing with a sub-Query, per discussion above */ break; case T_WindowClause: { WindowClause *wc = (WindowClause *) node; if (walker(wc->partitionClause, context)) return true; if (walker(wc->orderClause, context)) return true; if (walker(wc->startOffset, context)) return true; if (walker(wc->endOffset, context)) return true; } break; case T_CommonTableExpr: { CommonTableExpr *cte = (CommonTableExpr *) node; /* * Invoke the walker on the CTE's Query node, so it can * recurse into the sub-query if it wants to. */ return walker(cte->ctequery, context); } break; case T_List: foreach(temp, (List *) node) { if (walker((Node *) lfirst(temp), context)) return true; } break; case T_FromExpr: { FromExpr *from = (FromExpr *) node; if (walker(from->fromlist, context)) return true; if (walker(from->quals, context)) return true; } break; case T_JoinExpr: { JoinExpr *join = (JoinExpr *) node; if (walker(join->larg, context)) return true; if (walker(join->rarg, context)) return true; if (walker(join->quals, context)) return true; /* * alias clause, using list are deemed uninteresting. */ } break; case T_SetOperationStmt: { SetOperationStmt *setop = (SetOperationStmt *) node; if (walker(setop->larg, context)) return true; if (walker(setop->rarg, context)) return true; /* groupClauses are deemed uninteresting */ } break; case T_PlaceHolderVar: return walker(((PlaceHolderVar *) node)->phexpr, context); case T_AppendRelInfo: { AppendRelInfo *appinfo = (AppendRelInfo *) node; if (expression_tree_walker((Node *) appinfo->translated_vars, walker, context)) return true; } break; case T_PlaceHolderInfo: return walker(((PlaceHolderInfo *) node)->ph_var, context); default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); break; } return false; }
Definition at line 849 of file nodeFuncs.c.
References nodeTag, T_Aggref, T_DistinctExpr, T_FuncExpr, T_MinMaxExpr, T_NullIfExpr, T_OpExpr, T_ScalarArrayOpExpr, and T_WindowFunc.
Referenced by resolve_polymorphic_tupdesc().
{ Oid coll; if (!expr) return InvalidOid; switch (nodeTag(expr)) { case T_Aggref: coll = ((const Aggref *) expr)->inputcollid; break; case T_WindowFunc: coll = ((const WindowFunc *) expr)->inputcollid; break; case T_FuncExpr: coll = ((const FuncExpr *) expr)->inputcollid; break; case T_OpExpr: coll = ((const OpExpr *) expr)->inputcollid; break; case T_DistinctExpr: coll = ((const DistinctExpr *) expr)->inputcollid; break; case T_NullIfExpr: coll = ((const NullIfExpr *) expr)->inputcollid; break; case T_ScalarArrayOpExpr: coll = ((const ScalarArrayOpExpr *) expr)->inputcollid; break; case T_MinMaxExpr: coll = ((const MinMaxExpr *) expr)->inputcollid; break; default: coll = InvalidOid; break; } return coll; }
Definition at line 485 of file nodeFuncs.c.
References FuncExpr::args, COERCE_EXPLICIT_CAST, COERCE_IMPLICIT_CAST, Const::constisnull, Const::consttype, Const::constvalue, DatumGetInt32, FuncExpr::funcformat, INT4OID, IsA, list_length(), lsecond, NULL, and ArrayCoerceExpr::resulttypmod.
Referenced by coerce_type(), deparseFuncExpr(), exprTypmod(), and get_func_expr().
{ if (coercedTypmod != NULL) *coercedTypmod = -1; /* default result on failure */ /* * Scalar-type length coercions are FuncExprs, array-type length coercions * are ArrayCoerceExprs */ if (expr && IsA(expr, FuncExpr)) { const FuncExpr *func = (const FuncExpr *) expr; int nargs; Const *second_arg; /* * If it didn't come from a coercion context, reject. */ if (func->funcformat != COERCE_EXPLICIT_CAST && func->funcformat != COERCE_IMPLICIT_CAST) return false; /* * If it's not a two-argument or three-argument function with the * second argument being an int4 constant, it can't have been created * from a length coercion (it must be a type coercion, instead). */ nargs = list_length(func->args); if (nargs < 2 || nargs > 3) return false; second_arg = (Const *) lsecond(func->args); if (!IsA(second_arg, Const) || second_arg->consttype != INT4OID || second_arg->constisnull) return false; /* * OK, it is indeed a length-coercion function. */ if (coercedTypmod != NULL) *coercedTypmod = DatumGetInt32(second_arg->constvalue); return true; } if (expr && IsA(expr, ArrayCoerceExpr)) { const ArrayCoerceExpr *acoerce = (const ArrayCoerceExpr *) expr; /* It's not a length coercion unless there's a nondefault typmod */ if (acoerce->resulttypmod < 0) return false; /* * OK, it is indeed a length-coercion expression. */ if (coercedTypmod != NULL) *coercedTypmod = acoerce->resulttypmod; return true; } return false; }
int exprLocation | ( | const Node * | expr | ) |
Definition at line 1105 of file nodeFuncs.c.
References TypeCast::arg, CoerceToDomain::arg, ConvertRowtypeExpr::arg, ArrayCoerceExpr::arg, CoerceViaIO::arg, RelabelType::arg, arg, NamedArgExpr::arg, FuncCall::args, XmlExpr::args, BoolExpr::args, ScalarArrayOpExpr::args, OpExpr::args, FuncExpr::args, exprLocation(), fc(), leftmostLoc(), A_Expr::lexpr, lfirst, TypeCast::location, TypeName::location, FuncCall::location, A_Expr::location, CoerceToDomain::location, XmlExpr::location, ConvertRowtypeExpr::location, ArrayCoerceExpr::location, CoerceViaIO::location, RelabelType::location, SubLink::location, BoolExpr::location, ScalarArrayOpExpr::location, OpExpr::location, NamedArgExpr::location, FuncExpr::location, nodeTag, NULL, T_A_ArrayExpr, T_A_Const, T_A_Expr, T_Aggref, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseWhen, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_CollateClause, T_CollateExpr, T_ColumnRef, T_CommonTableExpr, T_Const, T_Constraint, T_ConvertRowtypeExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncCall, T_FuncExpr, T_IntoClause, T_List, T_MinMaxExpr, T_NamedArgExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_ParamRef, T_PlaceHolderVar, T_RangeVar, T_RelabelType, T_ResTarget, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SetToDefault, T_SortBy, T_SubLink, T_TargetEntry, T_TypeCast, T_TypeName, T_Var, T_WindowDef, T_WindowFunc, T_WithClause, T_XmlExpr, T_XmlSerialize, SubLink::testexpr, and TypeCast::typeName.
Referenced by addRangeTableEntryForFunction(), addTargetToSortList(), analyzeCTE(), assign_collations_walker(), checkWellFormedRecursion(), coerce_to_boolean(), coerce_to_common_type(), coerce_to_specific_type(), exprLocation(), get_matching_location(), ParseFuncOrColumn(), parser_coercion_errposition(), select_common_type(), transformAExprOf(), transformAggregateCall(), transformArrayExpr(), transformArraySubscripts(), transformAssignedExpr(), transformDistinctClause(), transformDistinctOnClause(), transformGroupClause(), transformIndirection(), transformInsertRow(), transformInsertStmt(), transformSelectStmt(), transformSetOperationStmt(), transformSetOperationTree(), and transformValuesClause().
{ int loc; if (expr == NULL) return -1; switch (nodeTag(expr)) { case T_RangeVar: loc = ((const RangeVar *) expr)->location; break; case T_Var: loc = ((const Var *) expr)->location; break; case T_Const: loc = ((const Const *) expr)->location; break; case T_Param: loc = ((const Param *) expr)->location; break; case T_Aggref: /* function name should always be the first thing */ loc = ((const Aggref *) expr)->location; break; case T_WindowFunc: /* function name should always be the first thing */ loc = ((const WindowFunc *) expr)->location; break; case T_ArrayRef: /* just use array argument's location */ loc = exprLocation((Node *) ((const ArrayRef *) expr)->refexpr); break; case T_FuncExpr: { const FuncExpr *fexpr = (const FuncExpr *) expr; /* consider both function name and leftmost arg */ loc = leftmostLoc(fexpr->location, exprLocation((Node *) fexpr->args)); } break; case T_NamedArgExpr: { const NamedArgExpr *na = (const NamedArgExpr *) expr; /* consider both argument name and value */ loc = leftmostLoc(na->location, exprLocation((Node *) na->arg)); } break; case T_OpExpr: case T_DistinctExpr: /* struct-equivalent to OpExpr */ case T_NullIfExpr: /* struct-equivalent to OpExpr */ { const OpExpr *opexpr = (const OpExpr *) expr; /* consider both operator name and leftmost arg */ loc = leftmostLoc(opexpr->location, exprLocation((Node *) opexpr->args)); } break; case T_ScalarArrayOpExpr: { const ScalarArrayOpExpr *saopexpr = (const ScalarArrayOpExpr *) expr; /* consider both operator name and leftmost arg */ loc = leftmostLoc(saopexpr->location, exprLocation((Node *) saopexpr->args)); } break; case T_BoolExpr: { const BoolExpr *bexpr = (const BoolExpr *) expr; /* * Same as above, to handle either NOT or AND/OR. We can't * special-case NOT because of the way that it's used for * things like IS NOT BETWEEN. */ loc = leftmostLoc(bexpr->location, exprLocation((Node *) bexpr->args)); } break; case T_SubLink: { const SubLink *sublink = (const SubLink *) expr; /* check the testexpr, if any, and the operator/keyword */ loc = leftmostLoc(exprLocation(sublink->testexpr), sublink->location); } break; case T_FieldSelect: /* just use argument's location */ loc = exprLocation((Node *) ((const FieldSelect *) expr)->arg); break; case T_FieldStore: /* just use argument's location */ loc = exprLocation((Node *) ((const FieldStore *) expr)->arg); break; case T_RelabelType: { const RelabelType *rexpr = (const RelabelType *) expr; /* Much as above */ loc = leftmostLoc(rexpr->location, exprLocation((Node *) rexpr->arg)); } break; case T_CoerceViaIO: { const CoerceViaIO *cexpr = (const CoerceViaIO *) expr; /* Much as above */ loc = leftmostLoc(cexpr->location, exprLocation((Node *) cexpr->arg)); } break; case T_ArrayCoerceExpr: { const ArrayCoerceExpr *cexpr = (const ArrayCoerceExpr *) expr; /* Much as above */ loc = leftmostLoc(cexpr->location, exprLocation((Node *) cexpr->arg)); } break; case T_ConvertRowtypeExpr: { const ConvertRowtypeExpr *cexpr = (const ConvertRowtypeExpr *) expr; /* Much as above */ loc = leftmostLoc(cexpr->location, exprLocation((Node *) cexpr->arg)); } break; case T_CollateExpr: /* just use argument's location */ loc = exprLocation((Node *) ((const CollateExpr *) expr)->arg); break; case T_CaseExpr: /* CASE keyword should always be the first thing */ loc = ((const CaseExpr *) expr)->location; break; case T_CaseWhen: /* WHEN keyword should always be the first thing */ loc = ((const CaseWhen *) expr)->location; break; case T_ArrayExpr: /* the location points at ARRAY or [, which must be leftmost */ loc = ((const ArrayExpr *) expr)->location; break; case T_RowExpr: /* the location points at ROW or (, which must be leftmost */ loc = ((const RowExpr *) expr)->location; break; case T_RowCompareExpr: /* just use leftmost argument's location */ loc = exprLocation((Node *) ((const RowCompareExpr *) expr)->largs); break; case T_CoalesceExpr: /* COALESCE keyword should always be the first thing */ loc = ((const CoalesceExpr *) expr)->location; break; case T_MinMaxExpr: /* GREATEST/LEAST keyword should always be the first thing */ loc = ((const MinMaxExpr *) expr)->location; break; case T_XmlExpr: { const XmlExpr *xexpr = (const XmlExpr *) expr; /* consider both function name and leftmost arg */ loc = leftmostLoc(xexpr->location, exprLocation((Node *) xexpr->args)); } break; case T_NullTest: /* just use argument's location */ loc = exprLocation((Node *) ((const NullTest *) expr)->arg); break; case T_BooleanTest: /* just use argument's location */ loc = exprLocation((Node *) ((const BooleanTest *) expr)->arg); break; case T_CoerceToDomain: { const CoerceToDomain *cexpr = (const CoerceToDomain *) expr; /* Much as above */ loc = leftmostLoc(cexpr->location, exprLocation((Node *) cexpr->arg)); } break; case T_CoerceToDomainValue: loc = ((const CoerceToDomainValue *) expr)->location; break; case T_SetToDefault: loc = ((const SetToDefault *) expr)->location; break; case T_TargetEntry: /* just use argument's location */ loc = exprLocation((Node *) ((const TargetEntry *) expr)->expr); break; case T_IntoClause: /* use the contained RangeVar's location --- close enough */ loc = exprLocation((Node *) ((const IntoClause *) expr)->rel); break; case T_List: { /* report location of first list member that has a location */ ListCell *lc; loc = -1; /* just to suppress compiler warning */ foreach(lc, (const List *) expr) { loc = exprLocation((Node *) lfirst(lc)); if (loc >= 0) break; } } break; case T_A_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 */ loc = leftmostLoc(aexpr->location, exprLocation(aexpr->lexpr)); } break; case T_ColumnRef: loc = ((const ColumnRef *) expr)->location; break; case T_ParamRef: loc = ((const ParamRef *) expr)->location; break; case T_A_Const: loc = ((const A_Const *) expr)->location; break; case T_FuncCall: { 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) */ loc = leftmostLoc(fc->location, exprLocation((Node *) fc->args)); } break; case T_A_ArrayExpr: /* the location points at ARRAY or [, which must be leftmost */ loc = ((const A_ArrayExpr *) expr)->location; break; case T_ResTarget: /* we need not examine the contained expression (if any) */ loc = ((const ResTarget *) expr)->location; break; case T_TypeCast: { const TypeCast *tc = (const TypeCast *) expr; /* * This could represent CAST(), ::, or TypeName 'literal', so * any of the components might be leftmost. */ loc = exprLocation(tc->arg); loc = leftmostLoc(loc, tc->typeName->location); loc = leftmostLoc(loc, tc->location); } break; case T_CollateClause: /* just use argument's location */ loc = exprLocation(((const CollateClause *) expr)->arg); break; case T_SortBy: /* just use argument's location (ignore operator, if any) */ loc = exprLocation(((const SortBy *) expr)->node); break; case T_WindowDef: loc = ((const WindowDef *) expr)->location; break; case T_TypeName: loc = ((const TypeName *) expr)->location; break; case T_Constraint: loc = ((const Constraint *) expr)->location; break; case T_XmlSerialize: /* XMLSERIALIZE keyword should always be the first thing */ loc = ((const XmlSerialize *) expr)->location; break; case T_WithClause: loc = ((const WithClause *) expr)->location; break; case T_CommonTableExpr: loc = ((const CommonTableExpr *) expr)->location; break; case T_PlaceHolderVar: /* just use argument's location */ loc = exprLocation((Node *) ((const PlaceHolderVar *) expr)->phexpr); break; default: /* for any other node type it's just unknown... */ loc = -1; break; } return loc; }
Definition at line 897 of file nodeFuncs.c.
References arg, ARRAY_SUBLINK, Assert, DEFAULT_COLLATION_OID, elog, ERROR, EXPR_SUBLINK, exprCollation(), InvalidOid, IS_XMLSERIALIZE, IsA, linitial, nodeTag, OidIsValid, SubLink::subLinkType, SubLink::subselect, T_Aggref, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_MinMaxExpr, T_NamedArgExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SetToDefault, T_SubLink, T_Var, T_WindowFunc, T_XmlExpr, and Query::targetList.
Referenced by assign_collations_walker().
{ switch (nodeTag(expr)) { case T_Var: ((Var *) expr)->varcollid = collation; break; case T_Const: ((Const *) expr)->constcollid = collation; break; case T_Param: ((Param *) expr)->paramcollid = collation; break; case T_Aggref: ((Aggref *) expr)->aggcollid = collation; break; case T_WindowFunc: ((WindowFunc *) expr)->wincollid = collation; break; case T_ArrayRef: ((ArrayRef *) expr)->refcollid = collation; break; case T_FuncExpr: ((FuncExpr *) expr)->funccollid = collation; break; case T_NamedArgExpr: Assert(collation == exprCollation((Node *) ((NamedArgExpr *) expr)->arg)); break; case T_OpExpr: ((OpExpr *) expr)->opcollid = collation; break; case T_DistinctExpr: ((DistinctExpr *) expr)->opcollid = collation; break; case T_NullIfExpr: ((NullIfExpr *) expr)->opcollid = collation; break; case T_ScalarArrayOpExpr: Assert(!OidIsValid(collation)); /* result is always boolean */ break; case T_BoolExpr: Assert(!OidIsValid(collation)); /* result is always boolean */ break; case T_SubLink: #ifdef USE_ASSERT_CHECKING { SubLink *sublink = (SubLink *) expr; if (sublink->subLinkType == EXPR_SUBLINK || sublink->subLinkType == ARRAY_SUBLINK) { /* get the collation of subselect's first target column */ Query *qtree = (Query *) sublink->subselect; TargetEntry *tent; if (!qtree || !IsA(qtree, Query)) elog(ERROR, "cannot set collation for untransformed sublink"); tent = (TargetEntry *) linitial(qtree->targetList); Assert(IsA(tent, TargetEntry)); Assert(!tent->resjunk); Assert(collation == exprCollation((Node *) tent->expr)); } else { /* for all other sublink types, result is boolean */ Assert(!OidIsValid(collation)); } } #endif /* USE_ASSERT_CHECKING */ break; case T_FieldSelect: ((FieldSelect *) expr)->resultcollid = collation; break; case T_FieldStore: Assert(!OidIsValid(collation)); /* result is always composite */ break; case T_RelabelType: ((RelabelType *) expr)->resultcollid = collation; break; case T_CoerceViaIO: ((CoerceViaIO *) expr)->resultcollid = collation; break; case T_ArrayCoerceExpr: ((ArrayCoerceExpr *) expr)->resultcollid = collation; break; case T_ConvertRowtypeExpr: Assert(!OidIsValid(collation)); /* result is always composite */ break; case T_CaseExpr: ((CaseExpr *) expr)->casecollid = collation; break; case T_ArrayExpr: ((ArrayExpr *) expr)->array_collid = collation; break; case T_RowExpr: Assert(!OidIsValid(collation)); /* result is always composite */ break; case T_RowCompareExpr: Assert(!OidIsValid(collation)); /* result is always boolean */ break; case T_CoalesceExpr: ((CoalesceExpr *) expr)->coalescecollid = collation; break; case T_MinMaxExpr: ((MinMaxExpr *) expr)->minmaxcollid = collation; break; case T_XmlExpr: Assert((((XmlExpr *) expr)->op == IS_XMLSERIALIZE) ? (collation == DEFAULT_COLLATION_OID) : (collation == InvalidOid)); break; case T_NullTest: Assert(!OidIsValid(collation)); /* result is always boolean */ break; case T_BooleanTest: Assert(!OidIsValid(collation)); /* result is always boolean */ break; case T_CoerceToDomain: ((CoerceToDomain *) expr)->resultcollid = collation; break; case T_CoerceToDomainValue: ((CoerceToDomainValue *) expr)->collation = collation; break; case T_SetToDefault: ((SetToDefault *) expr)->collation = collation; break; case T_CurrentOfExpr: Assert(!OidIsValid(collation)); /* result is always boolean */ break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); break; } }
Definition at line 1041 of file nodeFuncs.c.
References nodeTag, T_Aggref, T_DistinctExpr, T_FuncExpr, T_MinMaxExpr, T_NullIfExpr, T_OpExpr, T_ScalarArrayOpExpr, and T_WindowFunc.
Referenced by assign_collations_walker().
{ switch (nodeTag(expr)) { case T_Aggref: ((Aggref *) expr)->inputcollid = inputcollation; break; case T_WindowFunc: ((WindowFunc *) expr)->inputcollid = inputcollation; break; case T_FuncExpr: ((FuncExpr *) expr)->inputcollid = inputcollation; break; case T_OpExpr: ((OpExpr *) expr)->inputcollid = inputcollation; break; case T_DistinctExpr: ((DistinctExpr *) expr)->inputcollid = inputcollation; break; case T_NullIfExpr: ((NullIfExpr *) expr)->inputcollid = inputcollation; break; case T_ScalarArrayOpExpr: ((ScalarArrayOpExpr *) expr)->inputcollid = inputcollation; break; case T_MinMaxExpr: ((MinMaxExpr *) expr)->inputcollid = inputcollation; break; default: break; } }
Definition at line 36 of file nodeFuncs.c.
References arg, ARRAY_SUBLINK, Assert, elog, ereport, errcode(), errmsg(), ERROR, EXPR_SUBLINK, exprType(), SubPlan::firstColType, format_type_be(), get_array_type(), IS_DOCUMENT, IS_XMLSERIALIZE, IsA, linitial, nodeTag, OidIsValid, ArrayRef::refarraytype, ArrayRef::refassgnexpr, ArrayRef::refelemtype, ArrayRef::reflowerindexpr, SubPlan::subLinkType, SubLink::subLinkType, AlternativeSubPlan::subplans, SubLink::subselect, T_Aggref, T_AlternativeSubPlan, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_CollateExpr, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_MinMaxExpr, T_NamedArgExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_PlaceHolderVar, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SetToDefault, T_SubLink, T_SubPlan, T_Var, T_WindowFunc, T_XmlExpr, and Query::targetList.
Referenced by addTargetToGroupList(), addTargetToSortList(), analyzeCTE(), analyzeCTETargetList(), assign_collations_walker(), assign_nestloop_param_placeholdervar(), ATExecAlterColumnType(), ATPrepAlterColumnType(), build_column_default(), build_subplan(), canonicalize_ec_expression(), check_hashjoinable(), check_mergejoinable(), check_sql_fn_retval(), checkRuleResultList(), coerce_record_to_complex(), coerce_to_boolean(), coerce_to_common_type(), coerce_to_specific_type(), compare_tlist_datatypes(), ComputeIndexAttrs(), ConstructTupleDescriptor(), contain_leaky_functions_walker(), contain_mutable_functions_walker(), contain_volatile_functions_walker(), convert_EXISTS_to_ANY(), cookDefault(), cost_qual_eval_walker(), count_agg_clauses_walker(), create_unique_path(), DefineVirtualRelation(), estimate_num_groups(), eval_const_expressions_mutator(), EvaluateParams(), examine_attribute(), examine_variable(), exec_simple_recheck_plan(), ExecCheckPlanOutput(), ExecEvalConvertRowtype(), ExecEvalXml(), ExecInitAgg(), ExecInitExpr(), ExecMakeTableFunctionResult(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), ExecWindowAgg(), expandRecordVariable(), ExpandRowReference(), expandRTE(), exprType(), exprTypmod(), find_minmax_aggs_walker(), find_placeholder_info(), fix_indexqual_operand(), foreign_expr_walker(), generate_append_tlist(), generate_join_implied_equalities_normal(), generate_setop_tlist(), generate_subquery_params(), generateClonedIndexStmt(), get_agg_expr(), get_call_expr_argtype(), get_expr_result_type(), get_first_col_type(), get_fn_expr_rettype(), get_func_expr(), get_name_for_var_field(), get_oper_expr(), get_rte_attribute_is_dropped(), get_rte_attribute_type(), get_rule_expr(), get_rule_orderby(), get_simple_binary_op_name(), get_sublink_expr(), get_windowfunc_expr(), hash_ok_operator(), initialize_peragg(), inline_function(), internal_get_result_type(), IsTidEqualClause(), make_agg_subplan(), make_op(), make_scalar_array_op(), makeVarFromTargetEntry(), makeWholeRowVar(), ParseFuncOrColumn(), pg_get_indexdef_worker(), postgresBeginForeignScan(), ProcedureCreate(), process_equivalence(), process_matched_tle(), recheck_cast_function_args(), relabel_to_typmod(), replace_outer_placeholdervar(), scalararraysel(), select_common_type(), set_append_rel_size(), set_dummy_tlist_references(), set_rel_width(), tlist_matches_coltypelist(), tlist_same_datatypes(), transformAExprNullIf(), transformAExprOf(), transformAggregateCall(), transformArrayExpr(), transformArraySubscripts(), transformAssignedExpr(), transformAssignmentIndirection(), transformAssignmentSubscripts(), transformCaseExpr(), transformCollateClause(), transformExprRecurse(), transformIndirection(), transformInsertStmt(), transformSetOperationTree(), transformSubLink(), transformTypeCast(), unknown_attribute(), and xmlelement().
{ Oid type; if (!expr) return InvalidOid; switch (nodeTag(expr)) { case T_Var: type = ((const Var *) expr)->vartype; break; case T_Const: type = ((const Const *) expr)->consttype; break; case T_Param: type = ((const Param *) expr)->paramtype; break; case T_Aggref: type = ((const Aggref *) expr)->aggtype; break; case T_WindowFunc: type = ((const WindowFunc *) expr)->wintype; break; case T_ArrayRef: { const ArrayRef *arrayref = (const ArrayRef *) expr; /* slice and/or store operations yield the array type */ if (arrayref->reflowerindexpr || arrayref->refassgnexpr) type = arrayref->refarraytype; else type = arrayref->refelemtype; } break; case T_FuncExpr: type = ((const FuncExpr *) expr)->funcresulttype; break; case T_NamedArgExpr: type = exprType((Node *) ((const NamedArgExpr *) expr)->arg); break; case T_OpExpr: type = ((const OpExpr *) expr)->opresulttype; break; case T_DistinctExpr: type = ((const DistinctExpr *) expr)->opresulttype; break; case T_NullIfExpr: type = ((const NullIfExpr *) expr)->opresulttype; break; case T_ScalarArrayOpExpr: type = BOOLOID; break; case T_BoolExpr: type = BOOLOID; break; case T_SubLink: { const SubLink *sublink = (const SubLink *) expr; if (sublink->subLinkType == EXPR_SUBLINK || sublink->subLinkType == ARRAY_SUBLINK) { /* get the type of the subselect's first target column */ Query *qtree = (Query *) sublink->subselect; TargetEntry *tent; if (!qtree || !IsA(qtree, Query)) elog(ERROR, "cannot get type for untransformed sublink"); tent = (TargetEntry *) linitial(qtree->targetList); Assert(IsA(tent, TargetEntry)); Assert(!tent->resjunk); type = exprType((Node *) tent->expr); if (sublink->subLinkType == ARRAY_SUBLINK) { type = get_array_type(type); if (!OidIsValid(type)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find array type for data type %s", format_type_be(exprType((Node *) tent->expr))))); } } else { /* for all other sublink types, result is boolean */ type = BOOLOID; } } break; case T_SubPlan: { const SubPlan *subplan = (const SubPlan *) expr; if (subplan->subLinkType == EXPR_SUBLINK || subplan->subLinkType == ARRAY_SUBLINK) { /* get the type of the subselect's first target column */ type = subplan->firstColType; if (subplan->subLinkType == ARRAY_SUBLINK) { type = get_array_type(type); if (!OidIsValid(type)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find array type for data type %s", format_type_be(subplan->firstColType)))); } } else { /* for all other subplan types, result is boolean */ type = BOOLOID; } } break; case T_AlternativeSubPlan: { const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr; /* subplans should all return the same thing */ type = exprType((Node *) linitial(asplan->subplans)); } break; case T_FieldSelect: type = ((const FieldSelect *) expr)->resulttype; break; case T_FieldStore: type = ((const FieldStore *) expr)->resulttype; break; case T_RelabelType: type = ((const RelabelType *) expr)->resulttype; break; case T_CoerceViaIO: type = ((const CoerceViaIO *) expr)->resulttype; break; case T_ArrayCoerceExpr: type = ((const ArrayCoerceExpr *) expr)->resulttype; break; case T_ConvertRowtypeExpr: type = ((const ConvertRowtypeExpr *) expr)->resulttype; break; case T_CollateExpr: type = exprType((Node *) ((const CollateExpr *) expr)->arg); break; case T_CaseExpr: type = ((const CaseExpr *) expr)->casetype; break; case T_CaseTestExpr: type = ((const CaseTestExpr *) expr)->typeId; break; case T_ArrayExpr: type = ((const ArrayExpr *) expr)->array_typeid; break; case T_RowExpr: type = ((const RowExpr *) expr)->row_typeid; break; case T_RowCompareExpr: type = BOOLOID; break; case T_CoalesceExpr: type = ((const CoalesceExpr *) expr)->coalescetype; break; case T_MinMaxExpr: type = ((const MinMaxExpr *) expr)->minmaxtype; break; case T_XmlExpr: if (((const XmlExpr *) expr)->op == IS_DOCUMENT) type = BOOLOID; else if (((const XmlExpr *) expr)->op == IS_XMLSERIALIZE) type = TEXTOID; else type = XMLOID; break; case T_NullTest: type = BOOLOID; break; case T_BooleanTest: type = BOOLOID; break; case T_CoerceToDomain: type = ((const CoerceToDomain *) expr)->resulttype; break; case T_CoerceToDomainValue: type = ((const CoerceToDomainValue *) expr)->typeId; break; case T_SetToDefault: type = ((const SetToDefault *) expr)->typeId; break; case T_CurrentOfExpr: type = BOOLOID; break; case T_PlaceHolderVar: type = exprType((Node *) ((const PlaceHolderVar *) expr)->phexpr); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); type = InvalidOid; /* keep compiler quiet */ break; } return type; }
Definition at line 245 of file nodeFuncs.c.
References arg, MinMaxExpr::args, CoalesceExpr::args, CaseExpr::args, OpExpr::args, ARRAY_SUBLINK, ArrayExpr::array_typeid, Assert, CaseExpr::casetype, CoalesceExpr::coalescetype, CaseExpr::defresult, ArrayExpr::element_typeid, ArrayExpr::elements, elog, ERROR, EXPR_SUBLINK, exprIsLengthCoercion(), exprType(), exprTypmod(), SubPlan::firstColTypmod, for_each_cell, IsA, lfirst, linitial, list_head(), lnext, MinMaxExpr::minmaxtype, ArrayExpr::multidims, NIL, nodeTag, CaseWhen::result, SubPlan::subLinkType, SubLink::subLinkType, AlternativeSubPlan::subplans, SubLink::subselect, T_AlternativeSubPlan, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CollateExpr, T_Const, T_FieldSelect, T_FuncExpr, T_MinMaxExpr, T_NamedArgExpr, T_NullIfExpr, T_Param, T_PlaceHolderVar, T_RelabelType, T_SetToDefault, T_SubLink, T_SubPlan, T_Var, and Query::targetList.
Referenced by analyzeCTE(), analyzeCTETargetList(), assign_nestloop_param_placeholdervar(), build_subplan(), canonicalize_ec_expression(), checkRuleResultList(), coerce_type_typmod(), convert_EXISTS_to_ANY(), count_agg_clauses_walker(), DefineVirtualRelation(), eval_const_expressions_mutator(), examine_attribute(), examine_variable(), ExecTypeFromExprList(), ExecTypeFromTLInternal(), expandRecordVariable(), ExpandRowReference(), expandRTE(), exprTypmod(), find_placeholder_info(), generate_append_tlist(), generate_setop_tlist(), generate_subquery_params(), get_first_col_type(), get_name_for_var_field(), get_rte_attribute_type(), interval_transform(), makeVarFromTargetEntry(), numeric_transform(), replace_outer_placeholdervar(), set_append_rel_size(), set_dummy_tlist_references(), set_rel_width(), TemporalTransform(), transformCaseExpr(), transformIndirection(), transformSetOperationTree(), transformSubLink(), varbit_transform(), and varchar_transform().
{ if (!expr) return -1; switch (nodeTag(expr)) { case T_Var: return ((const Var *) expr)->vartypmod; case T_Const: return ((const Const *) expr)->consttypmod; case T_Param: return ((const Param *) expr)->paramtypmod; case T_ArrayRef: /* typmod is the same for array or element */ return ((const ArrayRef *) expr)->reftypmod; case T_FuncExpr: { int32 coercedTypmod; /* Be smart about length-coercion functions... */ if (exprIsLengthCoercion(expr, &coercedTypmod)) return coercedTypmod; } break; case T_NamedArgExpr: return exprTypmod((Node *) ((const NamedArgExpr *) expr)->arg); case T_NullIfExpr: { /* * Result is either first argument or NULL, so we can report * first argument's typmod if known. */ const NullIfExpr *nexpr = (const NullIfExpr *) expr; return exprTypmod((Node *) linitial(nexpr->args)); } break; case T_SubLink: { const SubLink *sublink = (const SubLink *) expr; if (sublink->subLinkType == EXPR_SUBLINK || sublink->subLinkType == ARRAY_SUBLINK) { /* get the typmod of the subselect's first target column */ Query *qtree = (Query *) sublink->subselect; TargetEntry *tent; if (!qtree || !IsA(qtree, Query)) elog(ERROR, "cannot get type for untransformed sublink"); tent = (TargetEntry *) linitial(qtree->targetList); Assert(IsA(tent, TargetEntry)); Assert(!tent->resjunk); return exprTypmod((Node *) tent->expr); /* note we don't need to care if it's an array */ } } break; case T_SubPlan: { const SubPlan *subplan = (const SubPlan *) expr; if (subplan->subLinkType == EXPR_SUBLINK || subplan->subLinkType == ARRAY_SUBLINK) { /* get the typmod of the subselect's first target column */ /* note we don't need to care if it's an array */ return subplan->firstColTypmod; } else { /* for all other subplan types, result is boolean */ return -1; } } break; case T_AlternativeSubPlan: { const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr; /* subplans should all return the same thing */ return exprTypmod((Node *) linitial(asplan->subplans)); } break; case T_FieldSelect: return ((const FieldSelect *) expr)->resulttypmod; case T_RelabelType: return ((const RelabelType *) expr)->resulttypmod; case T_ArrayCoerceExpr: return ((const ArrayCoerceExpr *) expr)->resulttypmod; case T_CollateExpr: return exprTypmod((Node *) ((const CollateExpr *) expr)->arg); case T_CaseExpr: { /* * If all the alternatives agree on type/typmod, return that * typmod, else use -1 */ const CaseExpr *cexpr = (const CaseExpr *) expr; Oid casetype = cexpr->casetype; int32 typmod; ListCell *arg; if (!cexpr->defresult) return -1; if (exprType((Node *) cexpr->defresult) != casetype) return -1; typmod = exprTypmod((Node *) cexpr->defresult); if (typmod < 0) return -1; /* no point in trying harder */ foreach(arg, cexpr->args) { CaseWhen *w = (CaseWhen *) lfirst(arg); Assert(IsA(w, CaseWhen)); if (exprType((Node *) w->result) != casetype) return -1; if (exprTypmod((Node *) w->result) != typmod) return -1; } return typmod; } break; case T_CaseTestExpr: return ((const CaseTestExpr *) expr)->typeMod; case T_ArrayExpr: { /* * If all the elements agree on type/typmod, return that * typmod, else use -1 */ const ArrayExpr *arrayexpr = (const ArrayExpr *) expr; Oid commontype; int32 typmod; ListCell *elem; if (arrayexpr->elements == NIL) return -1; typmod = exprTypmod((Node *) linitial(arrayexpr->elements)); if (typmod < 0) return -1; /* no point in trying harder */ if (arrayexpr->multidims) commontype = arrayexpr->array_typeid; else commontype = arrayexpr->element_typeid; foreach(elem, arrayexpr->elements) { Node *e = (Node *) lfirst(elem); if (exprType(e) != commontype) return -1; if (exprTypmod(e) != typmod) return -1; } return typmod; } break; case T_CoalesceExpr: { /* * If all the alternatives agree on type/typmod, return that * typmod, else use -1 */ const CoalesceExpr *cexpr = (const CoalesceExpr *) expr; Oid coalescetype = cexpr->coalescetype; int32 typmod; ListCell *arg; if (exprType((Node *) linitial(cexpr->args)) != coalescetype) return -1; typmod = exprTypmod((Node *) linitial(cexpr->args)); if (typmod < 0) return -1; /* no point in trying harder */ for_each_cell(arg, lnext(list_head(cexpr->args))) { Node *e = (Node *) lfirst(arg); if (exprType(e) != coalescetype) return -1; if (exprTypmod(e) != typmod) return -1; } return typmod; } break; case T_MinMaxExpr: { /* * If all the alternatives agree on type/typmod, return that * typmod, else use -1 */ const MinMaxExpr *mexpr = (const MinMaxExpr *) expr; Oid minmaxtype = mexpr->minmaxtype; int32 typmod; ListCell *arg; if (exprType((Node *) linitial(mexpr->args)) != minmaxtype) return -1; typmod = exprTypmod((Node *) linitial(mexpr->args)); if (typmod < 0) return -1; /* no point in trying harder */ for_each_cell(arg, lnext(list_head(mexpr->args))) { Node *e = (Node *) lfirst(arg); if (exprType(e) != minmaxtype) return -1; if (exprTypmod(e) != typmod) return -1; } return typmod; } break; case T_CoerceToDomain: return ((const CoerceToDomain *) expr)->resulttypmod; case T_CoerceToDomainValue: return ((const CoerceToDomainValue *) expr)->typeMod; case T_SetToDefault: return ((const SetToDefault *) expr)->typeMod; case T_PlaceHolderVar: return exprTypmod((Node *) ((const PlaceHolderVar *) expr)->phexpr); default: break; } return -1; }
static int leftmostLoc | ( | int | loc1, | |
int | loc2 | |||
) | [static] |
Definition at line 1422 of file nodeFuncs.c.
References Min.
Referenced by exprLocation().
{ if (loc1 < 0) return loc2; else if (loc2 < 0) return loc1; else return Min(loc1, loc2); }
Node* query_or_expression_tree_mutator | ( | Node * | node, | |
Node *(*)() | mutator, | |||
void * | context, | |||
int | flags | |||
) |
Definition at line 2692 of file nodeFuncs.c.
References IsA, and query_tree_mutator().
Referenced by map_variable_attnos(), and replace_rte_variables().
{ if (node && IsA(node, Query)) return (Node *) query_tree_mutator((Query *) node, mutator, context, flags); else return mutator(node, context); }
Definition at line 2669 of file nodeFuncs.c.
References IsA, and query_tree_walker().
Referenced by attribute_used(), checkExprHasSubLink(), contain_aggs_of_level(), contain_vars_of_level(), contain_windowfuncs(), IncrementVarSublevelsUp(), locate_agg_of_level(), locate_var_of_level(), locate_windowfunc(), pull_varnos(), pull_varnos_of_level(), pull_vars_of_level(), rangeTableEntry_used(), and substitute_multiple_relids().
{ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, walker, context, flags); else return walker(node, context); }
Definition at line 2570 of file nodeFuncs.c.
References Assert, copyObject(), Query::cteList, FLATCOPY, Query::havingQual, IsA, Query::jointree, Query::limitCount, Query::limitOffset, MUTATE, NULL, QTW_DONT_COPY_QUERY, QTW_IGNORE_CTE_SUBQUERIES, range_table_mutator(), Query::returningList, Query::rtable, Query::setOperations, and Query::targetList.
Referenced by adjust_appendrel_attrs(), flatten_join_alias_vars_mutator(), map_variable_attnos_mutator(), query_or_expression_tree_mutator(), replace_rte_variables_mutator(), substitute_actual_srf_parameters(), and substitute_actual_srf_parameters_mutator().
{ Assert(query != NULL && IsA(query, Query)); if (!(flags & QTW_DONT_COPY_QUERY)) { Query *newquery; FLATCOPY(newquery, query, Query); query = newquery; } MUTATE(query->targetList, query->targetList, List *); MUTATE(query->returningList, query->returningList, List *); MUTATE(query->jointree, query->jointree, FromExpr *); MUTATE(query->setOperations, query->setOperations, Node *); MUTATE(query->havingQual, query->havingQual, Node *); MUTATE(query->limitOffset, query->limitOffset, Node *); MUTATE(query->limitCount, query->limitCount, Node *); if (!(flags & QTW_IGNORE_CTE_SUBQUERIES)) MUTATE(query->cteList, query->cteList, List *); else /* else copy CTE list as-is */ query->cteList = copyObject(query->cteList); query->rtable = range_table_mutator(query->rtable, mutator, context, flags); return query; }
Definition at line 1863 of file nodeFuncs.c.
References Assert, Query::cteList, Query::havingQual, IsA, Query::jointree, Query::limitCount, Query::limitOffset, NULL, QTW_IGNORE_CTE_SUBQUERIES, QTW_IGNORE_RANGE_TABLE, range_table_walker(), Query::returningList, Query::rtable, Query::setOperations, and Query::targetList.
Referenced by AcquireRewriteLocks(), assign_query_collations(), attribute_used_walker(), ChangeVarNodes(), ChangeVarNodes_walker(), check_agg_arguments_walker(), check_parameter_resolution_walker(), check_ungrouped_columns_walker(), check_variable_parameters(), contain_aggs_of_level_walker(), contain_vars_of_level_walker(), extract_query_dependencies_walker(), find_expr_references_walker(), fireRIRrules(), IncrementVarSublevelsUp_walker(), isQueryUsingTempRelation_walker(), locate_agg_of_level_walker(), locate_var_of_level_walker(), OffsetVarNodes(), OffsetVarNodes_walker(), pull_varnos_walker(), pull_vars_walker(), query_contains_extern_params(), query_contains_extern_params_walker(), query_or_expression_tree_walker(), rangeTableEntry_used_walker(), ScanQueryForLocks(), setRuleCheckAsUser_Query(), and substitute_multiple_relids_walker().
{ Assert(query != NULL && IsA(query, Query)); if (walker((Node *) query->targetList, context)) return true; if (walker((Node *) query->returningList, context)) return true; if (walker((Node *) query->jointree, context)) return true; if (walker(query->setOperations, context)) return true; if (walker(query->havingQual, context)) return true; if (walker(query->limitOffset, context)) return true; if (walker(query->limitCount, context)) return true; if (!(flags & QTW_IGNORE_CTE_SUBQUERIES)) { if (walker((Node *) query->cteList, context)) return true; } if (!(flags & QTW_IGNORE_RANGE_TABLE)) { if (range_table_walker(query->rtable, walker, context, flags)) return true; } return false; }
Definition at line 2607 of file nodeFuncs.c.
References CHECKFLATCOPY, copyObject(), FLATCOPY, RangeTblEntry::funcexpr, RangeTblEntry::joinaliasvars, lappend(), lfirst, MUTATE, QTW_IGNORE_JOINALIASES, QTW_IGNORE_RT_SUBQUERIES, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_RELATION, RTE_SUBQUERY, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::subquery, and RangeTblEntry::values_lists.
Referenced by query_tree_mutator().
{ List *newrt = NIL; ListCell *rt; foreach(rt, rtable) { RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt); RangeTblEntry *newrte; FLATCOPY(newrte, rte, RangeTblEntry); switch (rte->rtekind) { case RTE_RELATION: case RTE_CTE: /* we don't bother to copy eref, aliases, etc; OK? */ break; case RTE_SUBQUERY: if (!(flags & QTW_IGNORE_RT_SUBQUERIES)) { CHECKFLATCOPY(newrte->subquery, rte->subquery, Query); MUTATE(newrte->subquery, newrte->subquery, Query *); } else { /* else, copy RT subqueries as-is */ newrte->subquery = copyObject(rte->subquery); } break; case RTE_JOIN: if (!(flags & QTW_IGNORE_JOINALIASES)) MUTATE(newrte->joinaliasvars, rte->joinaliasvars, List *); else { /* else, copy join aliases as-is */ newrte->joinaliasvars = copyObject(rte->joinaliasvars); } break; case RTE_FUNCTION: MUTATE(newrte->funcexpr, rte->funcexpr, Node *); break; case RTE_VALUES: MUTATE(newrte->values_lists, rte->values_lists, List *); break; } newrt = lappend(newrt, newrte); } return newrt; }
Definition at line 1903 of file nodeFuncs.c.
References RangeTblEntry::funcexpr, RangeTblEntry::joinaliasvars, lfirst, QTW_EXAMINE_RTES, QTW_IGNORE_JOINALIASES, QTW_IGNORE_RT_SUBQUERIES, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_RELATION, RTE_SUBQUERY, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::subquery, and RangeTblEntry::values_lists.
Referenced by IncrementVarSublevelsUp_rtable(), and query_tree_walker().
{ ListCell *rt; foreach(rt, rtable) { RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt); /* For historical reasons, visiting RTEs is not the default */ if (flags & QTW_EXAMINE_RTES) if (walker(rte, context)) return true; switch (rte->rtekind) { case RTE_RELATION: case RTE_CTE: /* nothing to do */ break; case RTE_SUBQUERY: if (!(flags & QTW_IGNORE_RT_SUBQUERIES)) if (walker(rte->subquery, context)) return true; break; case RTE_JOIN: if (!(flags & QTW_IGNORE_JOINALIASES)) if (walker(rte->joinaliasvars, context)) return true; break; case RTE_FUNCTION: if (walker(rte->funcexpr, context)) return true; break; case RTE_VALUES: if (walker(rte->values_lists, context)) return true; break; } } return false; }
Definition at line 2721 of file nodeFuncs.c.
References FuncCall::agg_order, RangeFunction::alias, RangeSubselect::alias, JoinExpr::alias, TypeCast::arg, A_Indirection::arg, arg, CaseExpr::arg, FuncCall::args, XmlExpr::args, CaseExpr::args, TypeName::arrayBounds, Assert, check_stack_depth(), ColumnDef::collClause, InsertStmt::cols, CaseExpr::defresult, SelectStmt::distinctClause, elog, WindowDef::endOffset, ERROR, XmlSerialize::expr, CaseWhen::expr, SelectStmt::fromClause, UpdateStmt::fromClause, RangeFunction::funccallnode, SelectStmt::groupClause, SelectStmt::havingClause, ResTarget::indirection, A_Indirection::indirection, SelectStmt::intoClause, IsA, SelectStmt::larg, JoinExpr::larg, A_Expr::lexpr, lfirst, A_Indices::lidx, SelectStmt::limitCount, SelectStmt::limitOffset, SelectStmt::lockingClause, XmlExpr::named_args, nodeTag, NULL, WindowDef::orderClause, FuncCall::over, WindowDef::partitionClause, JoinExpr::quals, SelectStmt::rarg, JoinExpr::rarg, ColumnDef::raw_default, IntoClause::rel, UpdateStmt::relation, DeleteStmt::relation, InsertStmt::relation, CaseWhen::result, UpdateStmt::returningList, DeleteStmt::returningList, InsertStmt::returningList, A_Expr::rexpr, InsertStmt::selectStmt, SelectStmt::sortClause, WindowDef::startOffset, RangeSubselect::subquery, SubLink::subselect, T_A_ArrayExpr, T_A_Const, T_A_Expr, T_A_Indices, T_A_Indirection, T_A_Star, T_Alias, T_BitString, T_BooleanTest, T_CaseExpr, T_CoalesceExpr, T_CollateClause, T_ColumnDef, T_ColumnRef, T_CommonTableExpr, T_CurrentOfExpr, T_DeleteStmt, T_Float, T_FuncCall, T_InsertStmt, T_Integer, T_IntoClause, T_JoinExpr, T_List, T_LockingClause, T_MinMaxExpr, T_NamedArgExpr, T_Null, T_NullTest, T_ParamRef, T_RangeFunction, T_RangeSubselect, T_RangeVar, T_ResTarget, T_RowExpr, T_SelectStmt, T_SetToDefault, T_SortBy, T_String, T_SubLink, T_TypeCast, T_TypeName, T_UpdateStmt, T_WindowDef, T_WithClause, T_XmlExpr, T_XmlSerialize, SelectStmt::targetList, UpdateStmt::targetList, SubLink::testexpr, XmlSerialize::typeName, ColumnDef::typeName, TypeCast::typeName, TypeName::typmods, A_Indices::uidx, DeleteStmt::usingClause, ResTarget::val, SelectStmt::valuesLists, IntoClause::viewQuery, SelectStmt::whereClause, UpdateStmt::whereClause, DeleteStmt::whereClause, SelectStmt::windowClause, SelectStmt::withClause, UpdateStmt::withClause, DeleteStmt::withClause, and InsertStmt::withClause.
Referenced by checkWellFormedRecursionWalker(), checkWellFormedSelectStmt(), and makeDependencyGraphWalker().
{ ListCell *temp; /* * The walker has already visited the current node, and so we need only * recurse into any sub-nodes it has. */ if (node == NULL) return false; /* Guard against stack overflow due to overly complex expressions */ check_stack_depth(); switch (nodeTag(node)) { case T_SetToDefault: case T_CurrentOfExpr: case T_Integer: case T_Float: case T_String: case T_BitString: case T_Null: case T_ParamRef: case T_A_Const: case T_A_Star: /* primitive node types with no subnodes */ break; case T_Alias: /* we assume the colnames list isn't interesting */ break; case T_RangeVar: return walker(((RangeVar *) node)->alias, context); case T_SubLink: { SubLink *sublink = (SubLink *) node; if (walker(sublink->testexpr, context)) return true; /* we assume the operName is not interesting */ if (walker(sublink->subselect, context)) return true; } break; case T_CaseExpr: { CaseExpr *caseexpr = (CaseExpr *) node; if (walker(caseexpr->arg, context)) return true; /* we assume walker doesn't care about CaseWhens, either */ foreach(temp, caseexpr->args) { CaseWhen *when = (CaseWhen *) lfirst(temp); Assert(IsA(when, CaseWhen)); if (walker(when->expr, context)) return true; if (walker(when->result, context)) return true; } if (walker(caseexpr->defresult, context)) return true; } break; case T_RowExpr: /* Assume colnames isn't interesting */ return walker(((RowExpr *) node)->args, context); case T_CoalesceExpr: return walker(((CoalesceExpr *) node)->args, context); case T_MinMaxExpr: return walker(((MinMaxExpr *) node)->args, context); case T_XmlExpr: { XmlExpr *xexpr = (XmlExpr *) node; if (walker(xexpr->named_args, context)) return true; /* we assume walker doesn't care about arg_names */ if (walker(xexpr->args, context)) return true; } break; case T_NullTest: return walker(((NullTest *) node)->arg, context); case T_BooleanTest: return walker(((BooleanTest *) node)->arg, context); case T_JoinExpr: { JoinExpr *join = (JoinExpr *) node; if (walker(join->larg, context)) return true; if (walker(join->rarg, context)) return true; if (walker(join->quals, context)) return true; if (walker(join->alias, context)) return true; /* using list is deemed uninteresting */ } break; case T_IntoClause: { IntoClause *into = (IntoClause *) node; if (walker(into->rel, context)) return true; /* colNames, options are deemed uninteresting */ /* viewQuery should be null in raw parsetree, but check it */ if (walker(into->viewQuery, context)) return true; } break; case T_List: foreach(temp, (List *) node) { if (walker((Node *) lfirst(temp), context)) return true; } break; case T_InsertStmt: { InsertStmt *stmt = (InsertStmt *) node; if (walker(stmt->relation, context)) return true; if (walker(stmt->cols, context)) return true; if (walker(stmt->selectStmt, context)) return true; if (walker(stmt->returningList, context)) return true; if (walker(stmt->withClause, context)) return true; } break; case T_DeleteStmt: { DeleteStmt *stmt = (DeleteStmt *) node; if (walker(stmt->relation, context)) return true; if (walker(stmt->usingClause, context)) return true; if (walker(stmt->whereClause, context)) return true; if (walker(stmt->returningList, context)) return true; if (walker(stmt->withClause, context)) return true; } break; case T_UpdateStmt: { UpdateStmt *stmt = (UpdateStmt *) node; if (walker(stmt->relation, context)) return true; if (walker(stmt->targetList, context)) return true; if (walker(stmt->whereClause, context)) return true; if (walker(stmt->fromClause, context)) return true; if (walker(stmt->returningList, context)) return true; if (walker(stmt->withClause, context)) return true; } break; case T_SelectStmt: { SelectStmt *stmt = (SelectStmt *) node; if (walker(stmt->distinctClause, context)) return true; if (walker(stmt->intoClause, context)) return true; if (walker(stmt->targetList, context)) return true; if (walker(stmt->fromClause, context)) return true; if (walker(stmt->whereClause, context)) return true; if (walker(stmt->groupClause, context)) return true; if (walker(stmt->havingClause, context)) return true; if (walker(stmt->windowClause, context)) return true; if (walker(stmt->valuesLists, context)) return true; if (walker(stmt->sortClause, context)) return true; if (walker(stmt->limitOffset, context)) return true; if (walker(stmt->limitCount, context)) return true; if (walker(stmt->lockingClause, context)) return true; if (walker(stmt->withClause, context)) return true; if (walker(stmt->larg, context)) return true; if (walker(stmt->rarg, context)) return true; } break; case T_A_Expr: { A_Expr *expr = (A_Expr *) node; if (walker(expr->lexpr, context)) return true; if (walker(expr->rexpr, context)) return true; /* operator name is deemed uninteresting */ } break; case T_ColumnRef: /* we assume the fields contain nothing interesting */ break; case T_FuncCall: { FuncCall *fcall = (FuncCall *) node; if (walker(fcall->args, context)) return true; if (walker(fcall->agg_order, context)) return true; if (walker(fcall->over, context)) return true; /* function name is deemed uninteresting */ } break; case T_NamedArgExpr: return walker(((NamedArgExpr *) node)->arg, context); case T_A_Indices: { A_Indices *indices = (A_Indices *) node; if (walker(indices->lidx, context)) return true; if (walker(indices->uidx, context)) return true; } break; case T_A_Indirection: { A_Indirection *indir = (A_Indirection *) node; if (walker(indir->arg, context)) return true; if (walker(indir->indirection, context)) return true; } break; case T_A_ArrayExpr: return walker(((A_ArrayExpr *) node)->elements, context); case T_ResTarget: { ResTarget *rt = (ResTarget *) node; if (walker(rt->indirection, context)) return true; if (walker(rt->val, context)) return true; } break; case T_TypeCast: { TypeCast *tc = (TypeCast *) node; if (walker(tc->arg, context)) return true; if (walker(tc->typeName, context)) return true; } break; case T_CollateClause: return walker(((CollateClause *) node)->arg, context); case T_SortBy: return walker(((SortBy *) node)->node, context); case T_WindowDef: { WindowDef *wd = (WindowDef *) node; if (walker(wd->partitionClause, context)) return true; if (walker(wd->orderClause, context)) return true; if (walker(wd->startOffset, context)) return true; if (walker(wd->endOffset, context)) return true; } break; case T_RangeSubselect: { RangeSubselect *rs = (RangeSubselect *) node; if (walker(rs->subquery, context)) return true; if (walker(rs->alias, context)) return true; } break; case T_RangeFunction: { RangeFunction *rf = (RangeFunction *) node; if (walker(rf->funccallnode, context)) return true; if (walker(rf->alias, context)) return true; } break; case T_TypeName: { TypeName *tn = (TypeName *) node; if (walker(tn->typmods, context)) return true; if (walker(tn->arrayBounds, context)) return true; /* type name itself is deemed uninteresting */ } break; case T_ColumnDef: { ColumnDef *coldef = (ColumnDef *) node; if (walker(coldef->typeName, context)) return true; if (walker(coldef->raw_default, context)) return true; if (walker(coldef->collClause, context)) return true; /* for now, constraints are ignored */ } break; case T_LockingClause: return walker(((LockingClause *) node)->lockedRels, context); case T_XmlSerialize: { XmlSerialize *xs = (XmlSerialize *) node; if (walker(xs->expr, context)) return true; if (walker(xs->typeName, context)) return true; } break; case T_WithClause: return walker(((WithClause *) node)->ctes, context); case T_CommonTableExpr: return walker(((CommonTableExpr *) node)->ctequery, context); default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); break; } return false; }
Definition at line 560 of file nodeFuncs.c.
References arg, COERCE_EXPLICIT_CAST, exprCollation(), exprType(), IsA, and makeRelabelType().
Referenced by interval_transform(), numeric_transform(), TemporalTransform(), varbit_transform(), and varchar_transform().
{ 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_EXPLICIT_CAST); }