PostgreSQL Source Code git master
Loading...
Searching...
No Matches
clauses.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/pg_class.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_language.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "executor/functions.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/multibitmapset.h"
#include "nodes/nodeFuncs.h"
#include "nodes/subscripting.h"
#include "nodes/supportnodes.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/optimizer.h"
#include "optimizer/pathnode.h"
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
#include "parser/analyze.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteHandler.h"
#include "rewrite/rewriteManip.h"
#include "tcop/tcopprot.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/json.h"
#include "utils/jsonb.h"
#include "utils/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for clauses.c:

Go to the source code of this file.

Data Structures

struct  eval_const_expressions_context
 
struct  substitute_actual_parameters_context
 
struct  substitute_actual_parameters_in_from_context
 
struct  inline_error_callback_arg
 
struct  max_parallel_hazard_context
 

Macros

#define CCDN_CASETESTEXPR_OK   0x0001 /* CaseTestExpr okay here? */
 
#define MIN_ARRAY_SIZE_FOR_HASHED_SAOP   9
 
#define ece_generic_processing(node)
 
#define ece_all_arguments_const(node)    (!expression_tree_walker((Node *) (node), contain_non_const_walker, NULL))
 
#define ece_evaluate_expr(node)
 

Functions

static bool contain_agg_clause_walker (Node *node, void *context)
 
static bool find_window_functions_walker (Node *node, WindowFuncLists *lists)
 
static bool contain_subplans_walker (Node *node, void *context)
 
static bool contain_mutable_functions_walker (Node *node, void *context)
 
static bool contain_volatile_functions_walker (Node *node, void *context)
 
static bool contain_volatile_functions_not_nextval_walker (Node *node, void *context)
 
static bool max_parallel_hazard_walker (Node *node, max_parallel_hazard_context *context)
 
static bool contain_nonstrict_functions_walker (Node *node, void *context)
 
static bool contain_exec_param_walker (Node *node, List *param_ids)
 
static bool contain_context_dependent_node (Node *clause)
 
static bool contain_context_dependent_node_walker (Node *node, int *flags)
 
static bool contain_leaked_vars_walker (Node *node, void *context)
 
static Relids find_nonnullable_rels_walker (Node *node, bool top_level)
 
static Listfind_nonnullable_vars_walker (Node *node, bool top_level)
 
static void find_subquery_safe_quals (Node *jtnode, List **safe_quals)
 
static bool is_strict_saop (ScalarArrayOpExpr *expr, bool falseOK)
 
static bool convert_saop_to_hashed_saop_walker (Node *node, void *context)
 
static Nodeeval_const_expressions_mutator (Node *node, eval_const_expressions_context *context)
 
static bool contain_non_const_walker (Node *node, void *context)
 
static bool ece_function_is_safe (Oid funcid, eval_const_expressions_context *context)
 
static Listsimplify_or_arguments (List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceTrue)
 
static Listsimplify_and_arguments (List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceFalse)
 
static Nodesimplify_boolean_equality (Oid opno, List *args)
 
static Exprsimplify_function (Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, List **args_p, bool funcvariadic, bool process_args, bool allow_non_const, eval_const_expressions_context *context)
 
static Nodesimplify_aggref (Aggref *aggref, eval_const_expressions_context *context)
 
static Listreorder_function_arguments (List *args, int pronargs, HeapTuple func_tuple)
 
static Listadd_function_defaults (List *args, int pronargs, HeapTuple func_tuple)
 
static Listfetch_function_defaults (HeapTuple func_tuple)
 
static void recheck_cast_function_args (List *args, Oid result_type, Oid *proargtypes, int pronargs, HeapTuple func_tuple)
 
static Exprevaluate_function (Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, List *args, bool funcvariadic, HeapTuple func_tuple, eval_const_expressions_context *context)
 
static Exprinline_function (Oid funcid, Oid result_type, Oid result_collid, Oid input_collid, List *args, bool funcvariadic, HeapTuple func_tuple, eval_const_expressions_context *context)
 
static Nodesubstitute_actual_parameters (Node *expr, int nargs, List *args, int *usecounts)
 
static Nodesubstitute_actual_parameters_mutator (Node *node, substitute_actual_parameters_context *context)
 
static void sql_inline_error_callback (void *arg)
 
static Queryinline_sql_function_in_from (PlannerInfo *root, RangeTblFunction *rtfunc, FuncExpr *fexpr, HeapTuple func_tuple, Form_pg_proc funcform, const char *src)
 
static Querysubstitute_actual_parameters_in_from (Query *expr, int nargs, List *args)
 
static Nodesubstitute_actual_parameters_in_from_mutator (Node *node, substitute_actual_parameters_in_from_context *context)
 
static bool pull_paramids_walker (Node *node, Bitmapset **context)
 
bool contain_agg_clause (Node *clause)
 
bool contain_window_function (Node *clause)
 
WindowFuncListsfind_window_functions (Node *clause, Index maxWinRef)
 
double expression_returns_set_rows (PlannerInfo *root, Node *clause)
 
bool contain_subplans (Node *clause)
 
bool contain_mutable_functions (Node *clause)
 
static bool contain_mutable_functions_checker (Oid func_id, void *context)
 
bool contain_mutable_functions_after_planning (Expr *expr)
 
bool contain_volatile_functions (Node *clause)
 
static bool contain_volatile_functions_checker (Oid func_id, void *context)
 
bool contain_volatile_functions_after_planning (Expr *expr)
 
bool contain_volatile_functions_not_nextval (Node *clause)
 
static bool contain_volatile_functions_not_nextval_checker (Oid func_id, void *context)
 
char max_parallel_hazard (Query *parse)
 
bool is_parallel_safe (PlannerInfo *root, Node *node)
 
static bool max_parallel_hazard_test (char proparallel, max_parallel_hazard_context *context)
 
static bool max_parallel_hazard_checker (Oid func_id, void *context)
 
bool contain_nonstrict_functions (Node *clause)
 
static bool contain_nonstrict_functions_checker (Oid func_id, void *context)
 
bool contain_exec_param (Node *clause, List *param_ids)
 
bool contain_leaked_vars (Node *clause)
 
static bool contain_leaked_vars_checker (Oid func_id, void *context)
 
Relids find_nonnullable_rels (Node *clause)
 
Listfind_nonnullable_vars (Node *clause)
 
Listfind_forced_null_vars (Node *node)
 
Varfind_forced_null_var (Node *node)
 
bool query_outputs_are_not_nullable (Query *query)
 
bool is_pseudo_constant_clause (Node *clause)
 
bool is_pseudo_constant_clause_relids (Node *clause, Relids relids)
 
int NumRelids (PlannerInfo *root, Node *clause)
 
void CommuteOpExpr (OpExpr *clause)
 
static bool rowtype_field_matches (Oid rowtypeid, int fieldnum, Oid expectedtype, int32 expectedtypmod, Oid expectedcollation)
 
Nodeeval_const_expressions (PlannerInfo *root, Node *node)
 
void convert_saop_to_hashed_saop (Node *node)
 
Nodeestimate_expression_value (PlannerInfo *root, Node *node)
 
bool var_is_nonnullable (PlannerInfo *root, Var *var, NotNullSource source)
 
bool expr_is_nonnullable (PlannerInfo *root, Expr *expr, NotNullSource source)
 
Listexpand_function_arguments (List *args, bool include_out_arguments, Oid result_type, HeapTuple func_tuple)
 
Exprevaluate_expr (Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
 
Queryinline_function_in_from (PlannerInfo *root, RangeTblEntry *rte)
 
Bitmapsetpull_paramids (Expr *expr)
 
ScalarArrayOpExprmake_SAOP_expr (Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid, Oid inputcollid, List *exprs, bool haveNonConst)
 

Macro Definition Documentation

◆ CCDN_CASETESTEXPR_OK

#define CCDN_CASETESTEXPR_OK   0x0001 /* CaseTestExpr okay here? */

Definition at line 1201 of file clauses.c.

◆ ece_all_arguments_const

#define ece_all_arguments_const (   node)     (!expression_tree_walker((Node *) (node), contain_non_const_walker, NULL))

Definition at line 2672 of file clauses.c.

2687{
2688
2689 /* since this function recurses, it could be driven to stack overflow */
2691
2692 if (node == NULL)
2693 return NULL;
2694 switch (nodeTag(node))
2695 {
2696 case T_Param:
2697 {
2698 Param *param = (Param *) node;
2699 ParamListInfo paramLI = context->boundParams;
2700
2701 /* Look to see if we've been given a value for this Param */
2702 if (param->paramkind == PARAM_EXTERN &&
2703 paramLI != NULL &&
2704 param->paramid > 0 &&
2705 param->paramid <= paramLI->numParams)
2706 {
2709
2710 /*
2711 * Give hook a chance in case parameter is dynamic. Tell
2712 * it that this fetch is speculative, so it should avoid
2713 * erroring out if parameter is unavailable.
2714 */
2715 if (paramLI->paramFetch != NULL)
2716 prm = paramLI->paramFetch(paramLI, param->paramid,
2717 true, &prmdata);
2718 else
2719 prm = &paramLI->params[param->paramid - 1];
2720
2721 /*
2722 * We don't just check OidIsValid, but insist that the
2723 * fetched type match the Param, just in case the hook did
2724 * something unexpected. No need to throw an error here
2725 * though; leave that for runtime.
2726 */
2727 if (OidIsValid(prm->ptype) &&
2728 prm->ptype == param->paramtype)
2729 {
2730 /* OK to substitute parameter value? */
2731 if (context->estimate ||
2732 (prm->pflags & PARAM_FLAG_CONST))
2733 {
2734 /*
2735 * Return a Const representing the param value.
2736 * Must copy pass-by-ref datatypes, since the
2737 * Param might be in a memory context
2738 * shorter-lived than our output plan should be.
2739 */
2740 int16 typLen;
2741 bool typByVal;
2742 Datum pval;
2743 Const *con;
2744
2746 &typLen, &typByVal);
2747 if (prm->isnull || typByVal)
2748 pval = prm->value;
2749 else
2750 pval = datumCopy(prm->value, typByVal, typLen);
2751 con = makeConst(param->paramtype,
2752 param->paramtypmod,
2753 param->paramcollid,
2754 (int) typLen,
2755 pval,
2756 prm->isnull,
2757 typByVal);
2758 con->location = param->location;
2759 return (Node *) con;
2760 }
2761 }
2762 }
2763
2764 /*
2765 * Not replaceable, so just copy the Param (no need to
2766 * recurse)
2767 */
2768 return (Node *) copyObject(param);
2769 }
2770 case T_WindowFunc:
2771 {
2772 WindowFunc *expr = (WindowFunc *) node;
2773 Oid funcid = expr->winfnoid;
2774 List *args;
2775 Expr *aggfilter;
2778
2779 /*
2780 * We can't really simplify a WindowFunc node, but we mustn't
2781 * just fall through to the default processing, because we
2782 * have to apply expand_function_arguments to its argument
2783 * list. That takes care of inserting default arguments and
2784 * expanding named-argument notation.
2785 */
2788 elog(ERROR, "cache lookup failed for function %u", funcid);
2789
2791 false, expr->wintype,
2792 func_tuple);
2793
2795
2796 /* Now, recursively simplify the args (which are a List) */
2797 args = (List *)
2800 context);
2801 /* ... and the filter expression, which isn't */
2802 aggfilter = (Expr *)
2804 context);
2805
2806 /* And build the replacement WindowFunc node */
2808 newexpr->winfnoid = expr->winfnoid;
2809 newexpr->wintype = expr->wintype;
2810 newexpr->wincollid = expr->wincollid;
2811 newexpr->inputcollid = expr->inputcollid;
2812 newexpr->args = args;
2813 newexpr->aggfilter = aggfilter;
2814 newexpr->runCondition = expr->runCondition;
2815 newexpr->winref = expr->winref;
2816 newexpr->winstar = expr->winstar;
2817 newexpr->winagg = expr->winagg;
2819 newexpr->location = expr->location;
2820
2821 return (Node *) newexpr;
2822 }
2823 case T_FuncExpr:
2824 {
2825 FuncExpr *expr = (FuncExpr *) node;
2826 List *args = expr->args;
2827 Expr *simple;
2829
2830 /*
2831 * Code for op/func reduction is pretty bulky, so split it out
2832 * as a separate function. Note: exprTypmod normally returns
2833 * -1 for a FuncExpr, but not when the node is recognizably a
2834 * length coercion; we want to preserve the typmod in the
2835 * eventual Const if so.
2836 */
2837 simple = simplify_function(expr->funcid,
2838 expr->funcresulttype,
2839 exprTypmod(node),
2840 expr->funccollid,
2841 expr->inputcollid,
2842 &args,
2843 expr->funcvariadic,
2844 true,
2845 true,
2846 context);
2847 if (simple) /* successfully simplified it */
2848 return (Node *) simple;
2849
2850 /*
2851 * The expression cannot be simplified any further, so build
2852 * and return a replacement FuncExpr node using the
2853 * possibly-simplified arguments. Note that we have also
2854 * converted the argument list to positional notation.
2855 */
2857 newexpr->funcid = expr->funcid;
2858 newexpr->funcresulttype = expr->funcresulttype;
2859 newexpr->funcretset = expr->funcretset;
2860 newexpr->funcvariadic = expr->funcvariadic;
2861 newexpr->funcformat = expr->funcformat;
2862 newexpr->funccollid = expr->funccollid;
2863 newexpr->inputcollid = expr->inputcollid;
2864 newexpr->args = args;
2865 newexpr->location = expr->location;
2866 return (Node *) newexpr;
2867 }
2868 case T_Aggref:
2869 node = ece_generic_processing(node);
2870 if (context->root != NULL)
2871 return simplify_aggref((Aggref *) node, context);
2872 return node;
2873 case T_OpExpr:
2874 {
2875 OpExpr *expr = (OpExpr *) node;
2876 List *args = expr->args;
2877 Expr *simple;
2878 OpExpr *newexpr;
2879
2880 /*
2881 * Need to get OID of underlying function. Okay to scribble
2882 * on input to this extent.
2883 */
2884 set_opfuncid(expr);
2885
2886 /*
2887 * Code for op/func reduction is pretty bulky, so split it out
2888 * as a separate function.
2889 */
2890 simple = simplify_function(expr->opfuncid,
2891 expr->opresulttype, -1,
2892 expr->opcollid,
2893 expr->inputcollid,
2894 &args,
2895 false,
2896 true,
2897 true,
2898 context);
2899 if (simple) /* successfully simplified it */
2900 return (Node *) simple;
2901
2902 /*
2903 * If the operator is boolean equality or inequality, we know
2904 * how to simplify cases involving one constant and one
2905 * non-constant argument.
2906 */
2907 if (expr->opno == BooleanEqualOperator ||
2909 {
2910 simple = (Expr *) simplify_boolean_equality(expr->opno,
2911 args);
2912 if (simple) /* successfully simplified it */
2913 return (Node *) simple;
2914 }
2915
2916 /*
2917 * The expression cannot be simplified any further, so build
2918 * and return a replacement OpExpr node using the
2919 * possibly-simplified arguments.
2920 */
2922 newexpr->opno = expr->opno;
2923 newexpr->opfuncid = expr->opfuncid;
2924 newexpr->opresulttype = expr->opresulttype;
2925 newexpr->opretset = expr->opretset;
2926 newexpr->opcollid = expr->opcollid;
2927 newexpr->inputcollid = expr->inputcollid;
2928 newexpr->args = args;
2929 newexpr->location = expr->location;
2930 return (Node *) newexpr;
2931 }
2932 case T_DistinctExpr:
2933 {
2934 DistinctExpr *expr = (DistinctExpr *) node;
2935 List *args;
2936 ListCell *arg;
2937 bool has_null_input = false;
2938 bool all_null_input = true;
2939 bool has_nonconst_input = false;
2940 bool has_nullable_nonconst = false;
2941 Expr *simple;
2943
2944 /*
2945 * Reduce constants in the DistinctExpr's arguments. We know
2946 * args is either NIL or a List node, so we can call
2947 * expression_tree_mutator directly rather than recursing to
2948 * self.
2949 */
2950 args = (List *) expression_tree_mutator((Node *) expr->args,
2952 context);
2953
2954 /*
2955 * We must do our own check for NULLs because DistinctExpr has
2956 * different results for NULL input than the underlying
2957 * operator does. We also check if any non-constant input is
2958 * potentially nullable.
2959 */
2960 foreach(arg, args)
2961 {
2962 if (IsA(lfirst(arg), Const))
2963 {
2966 }
2967 else
2968 {
2969 has_nonconst_input = true;
2970 all_null_input = false;
2971
2972 if (!has_nullable_nonconst &&
2973 !expr_is_nonnullable(context->root,
2974 (Expr *) lfirst(arg),
2976 has_nullable_nonconst = true;
2977 }
2978 }
2979
2980 if (!has_nonconst_input)
2981 {
2982 /*
2983 * All inputs are constants. We can optimize this out
2984 * completely.
2985 */
2986
2987 /* all nulls? then not distinct */
2988 if (all_null_input)
2989 return makeBoolConst(false, false);
2990
2991 /* one null? then distinct */
2992 if (has_null_input)
2993 return makeBoolConst(true, false);
2994
2995 /* otherwise try to evaluate the '=' operator */
2996 /* (NOT okay to try to inline it, though!) */
2997
2998 /*
2999 * Need to get OID of underlying function. Okay to
3000 * scribble on input to this extent.
3001 */
3002 set_opfuncid((OpExpr *) expr); /* rely on struct
3003 * equivalence */
3004
3005 /*
3006 * Code for op/func reduction is pretty bulky, so split it
3007 * out as a separate function.
3008 */
3009 simple = simplify_function(expr->opfuncid,
3010 expr->opresulttype, -1,
3011 expr->opcollid,
3012 expr->inputcollid,
3013 &args,
3014 false,
3015 false,
3016 false,
3017 context);
3018 if (simple) /* successfully simplified it */
3019 {
3020 /*
3021 * Since the underlying operator is "=", must negate
3022 * its result
3023 */
3024 Const *csimple = castNode(Const, simple);
3025
3026 csimple->constvalue =
3027 BoolGetDatum(!DatumGetBool(csimple->constvalue));
3028 return (Node *) csimple;
3029 }
3030 }
3031 else if (!has_nullable_nonconst)
3032 {
3033 /*
3034 * There are non-constant inputs, but since all of them
3035 * are proven non-nullable, "IS DISTINCT FROM" semantics
3036 * are much simpler.
3037 */
3038
3039 OpExpr *eqexpr;
3040
3041 /*
3042 * If one input is an explicit NULL constant, and the
3043 * other is a non-nullable expression, the result is
3044 * always TRUE.
3045 */
3046 if (has_null_input)
3047 return makeBoolConst(true, false);
3048
3049 /*
3050 * Otherwise, both inputs are known non-nullable. In this
3051 * case, "IS DISTINCT FROM" is equivalent to the standard
3052 * inequality operator (usually "<>"). We convert this to
3053 * an OpExpr, which is a more efficient representation for
3054 * the planner. It can enable the use of partial indexes
3055 * and constraint exclusion. Furthermore, if the clause
3056 * is negated (ie, "IS NOT DISTINCT FROM"), the resulting
3057 * "=" operator can allow the planner to use index scans,
3058 * merge joins, hash joins, and EC-based qual deductions.
3059 */
3061 eqexpr->opno = expr->opno;
3062 eqexpr->opfuncid = expr->opfuncid;
3063 eqexpr->opresulttype = BOOLOID;
3064 eqexpr->opretset = expr->opretset;
3065 eqexpr->opcollid = expr->opcollid;
3066 eqexpr->inputcollid = expr->inputcollid;
3067 eqexpr->args = args;
3068 eqexpr->location = expr->location;
3069
3071 context);
3072 }
3073 else if (has_null_input)
3074 {
3075 /*
3076 * One input is a nullable non-constant expression, and
3077 * the other is an explicit NULL constant. We can
3078 * transform this to a NullTest with !argisrow, which is
3079 * much more amenable to optimization.
3080 */
3081
3083
3084 nt->arg = (Expr *) (IsA(linitial(args), Const) ?
3085 lsecond(args) : linitial(args));
3086 nt->nulltesttype = IS_NOT_NULL;
3087
3088 /*
3089 * argisrow = false is correct whether or not arg is
3090 * composite
3091 */
3092 nt->argisrow = false;
3093 nt->location = expr->location;
3094
3095 return eval_const_expressions_mutator((Node *) nt, context);
3096 }
3097
3098 /*
3099 * The expression cannot be simplified any further, so build
3100 * and return a replacement DistinctExpr node using the
3101 * possibly-simplified arguments.
3102 */
3104 newexpr->opno = expr->opno;
3105 newexpr->opfuncid = expr->opfuncid;
3106 newexpr->opresulttype = expr->opresulttype;
3107 newexpr->opretset = expr->opretset;
3108 newexpr->opcollid = expr->opcollid;
3109 newexpr->inputcollid = expr->inputcollid;
3110 newexpr->args = args;
3111 newexpr->location = expr->location;
3112 return (Node *) newexpr;
3113 }
3114 case T_NullIfExpr:
3115 {
3116 NullIfExpr *expr;
3117 ListCell *arg;
3118 bool has_nonconst_input = false;
3119
3120 /* Copy the node and const-simplify its arguments */
3121 expr = (NullIfExpr *) ece_generic_processing(node);
3122
3123 /* If either argument is NULL they can't be equal */
3124 foreach(arg, expr->args)
3125 {
3126 if (!IsA(lfirst(arg), Const))
3127 has_nonconst_input = true;
3128 else if (((Const *) lfirst(arg))->constisnull)
3129 return (Node *) linitial(expr->args);
3130 }
3131
3132 /*
3133 * Need to get OID of underlying function before checking if
3134 * the function is OK to evaluate.
3135 */
3136 set_opfuncid((OpExpr *) expr);
3137
3138 if (!has_nonconst_input &&
3139 ece_function_is_safe(expr->opfuncid, context))
3140 return ece_evaluate_expr(expr);
3141
3142 return (Node *) expr;
3143 }
3145 {
3146 ScalarArrayOpExpr *saop;
3147
3148 /* Copy the node and const-simplify its arguments */
3150
3151 /* Make sure we know underlying function */
3152 set_sa_opfuncid(saop);
3153
3154 /*
3155 * If all arguments are Consts, and it's a safe function, we
3156 * can fold to a constant
3157 */
3158 if (ece_all_arguments_const(saop) &&
3159 ece_function_is_safe(saop->opfuncid, context))
3160 return ece_evaluate_expr(saop);
3161 return (Node *) saop;
3162 }
3163 case T_BoolExpr:
3164 {
3165 BoolExpr *expr = (BoolExpr *) node;
3166
3167 switch (expr->boolop)
3168 {
3169 case OR_EXPR:
3170 {
3171 List *newargs;
3172 bool haveNull = false;
3173 bool forceTrue = false;
3174
3176 context,
3177 &haveNull,
3178 &forceTrue);
3179 if (forceTrue)
3180 return makeBoolConst(true, false);
3181 if (haveNull)
3183 makeBoolConst(false, true));
3184 /* If all the inputs are FALSE, result is FALSE */
3185 if (newargs == NIL)
3186 return makeBoolConst(false, false);
3187
3188 /*
3189 * If only one nonconst-or-NULL input, it's the
3190 * result
3191 */
3192 if (list_length(newargs) == 1)
3193 return (Node *) linitial(newargs);
3194 /* Else we still need an OR node */
3195 return (Node *) make_orclause(newargs);
3196 }
3197 case AND_EXPR:
3198 {
3199 List *newargs;
3200 bool haveNull = false;
3201 bool forceFalse = false;
3202
3204 context,
3205 &haveNull,
3206 &forceFalse);
3207 if (forceFalse)
3208 return makeBoolConst(false, false);
3209 if (haveNull)
3211 makeBoolConst(false, true));
3212 /* If all the inputs are TRUE, result is TRUE */
3213 if (newargs == NIL)
3214 return makeBoolConst(true, false);
3215
3216 /*
3217 * If only one nonconst-or-NULL input, it's the
3218 * result
3219 */
3220 if (list_length(newargs) == 1)
3221 return (Node *) linitial(newargs);
3222 /* Else we still need an AND node */
3223 return (Node *) make_andclause(newargs);
3224 }
3225 case NOT_EXPR:
3226 {
3227 Node *arg;
3228
3229 Assert(list_length(expr->args) == 1);
3231 context);
3232
3233 /*
3234 * Use negate_clause() to see if we can simplify
3235 * away the NOT.
3236 */
3237 return negate_clause(arg);
3238 }
3239 default:
3240 elog(ERROR, "unrecognized boolop: %d",
3241 (int) expr->boolop);
3242 break;
3243 }
3244 break;
3245 }
3246
3247 case T_JsonValueExpr:
3248 {
3249 JsonValueExpr *jve = (JsonValueExpr *) node;
3250 Node *raw_expr = (Node *) jve->raw_expr;
3251 Node *formatted_expr = (Node *) jve->formatted_expr;
3252
3253 /*
3254 * If we can fold formatted_expr to a constant, we can elide
3255 * the JsonValueExpr altogether. Otherwise we must process
3256 * raw_expr too. But JsonFormat is a flat node and requires
3257 * no simplification, only copying.
3258 */
3259 formatted_expr = eval_const_expressions_mutator(formatted_expr,
3260 context);
3261 if (formatted_expr && IsA(formatted_expr, Const))
3262 return formatted_expr;
3263
3264 raw_expr = eval_const_expressions_mutator(raw_expr, context);
3265
3266 return (Node *) makeJsonValueExpr((Expr *) raw_expr,
3267 (Expr *) formatted_expr,
3268 copyObject(jve->format));
3269 }
3270
3271 case T_SubPlan:
3273
3274 /*
3275 * Return a SubPlan unchanged --- too late to do anything with it.
3276 *
3277 * XXX should we ereport() here instead? Probably this routine
3278 * should never be invoked after SubPlan creation.
3279 */
3280 return node;
3281 case T_RelabelType:
3282 {
3283 RelabelType *relabel = (RelabelType *) node;
3284 Node *arg;
3285
3286 /* Simplify the input ... */
3288 context);
3289 /* ... and attach a new RelabelType node, if needed */
3290 return applyRelabelType(arg,
3291 relabel->resulttype,
3292 relabel->resulttypmod,
3293 relabel->resultcollid,
3294 relabel->relabelformat,
3295 relabel->location,
3296 true);
3297 }
3298 case T_CoerceViaIO:
3299 {
3300 CoerceViaIO *expr = (CoerceViaIO *) node;
3301 List *args;
3302 Oid outfunc;
3303 bool outtypisvarlena;
3304 Oid infunc;
3306 Expr *simple;
3308
3309 /* Make a List so we can use simplify_function */
3310 args = list_make1(expr->arg);
3311
3312 /*
3313 * CoerceViaIO represents calling the source type's output
3314 * function then the result type's input function. So, try to
3315 * simplify it as though it were a stack of two such function
3316 * calls. First we need to know what the functions are.
3317 *
3318 * Note that the coercion functions are assumed not to care
3319 * about input collation, so we just pass InvalidOid for that.
3320 */
3324 &infunc, &intypioparam);
3325
3326 simple = simplify_function(outfunc,
3327 CSTRINGOID, -1,
3328 InvalidOid,
3329 InvalidOid,
3330 &args,
3331 false,
3332 true,
3333 true,
3334 context);
3335 if (simple) /* successfully simplified output fn */
3336 {
3337 /*
3338 * Input functions may want 1 to 3 arguments. We always
3339 * supply all three, trusting that nothing downstream will
3340 * complain.
3341 */
3342 args = list_make3(simple,
3344 -1,
3345 InvalidOid,
3346 sizeof(Oid),
3348 false,
3349 true),
3351 -1,
3352 InvalidOid,
3353 sizeof(int32),
3354 Int32GetDatum(-1),
3355 false,
3356 true));
3357
3358 simple = simplify_function(infunc,
3359 expr->resulttype, -1,
3360 expr->resultcollid,
3361 InvalidOid,
3362 &args,
3363 false,
3364 false,
3365 true,
3366 context);
3367 if (simple) /* successfully simplified input fn */
3368 return (Node *) simple;
3369 }
3370
3371 /*
3372 * The expression cannot be simplified any further, so build
3373 * and return a replacement CoerceViaIO node using the
3374 * possibly-simplified argument.
3375 */
3377 newexpr->arg = (Expr *) linitial(args);
3378 newexpr->resulttype = expr->resulttype;
3379 newexpr->resultcollid = expr->resultcollid;
3380 newexpr->coerceformat = expr->coerceformat;
3381 newexpr->location = expr->location;
3382 return (Node *) newexpr;
3383 }
3384 case T_ArrayCoerceExpr:
3385 {
3388
3389 /*
3390 * Copy the node and const-simplify its arguments. We can't
3391 * use ece_generic_processing() here because we need to mess
3392 * with case_val only while processing the elemexpr.
3393 */
3394 memcpy(ac, node, sizeof(ArrayCoerceExpr));
3395 ac->arg = (Expr *)
3397 context);
3398
3399 /*
3400 * Set up for the CaseTestExpr node contained in the elemexpr.
3401 * We must prevent it from absorbing any outer CASE value.
3402 */
3403 save_case_val = context->case_val;
3404 context->case_val = NULL;
3405
3406 ac->elemexpr = (Expr *)
3408 context);
3409
3410 context->case_val = save_case_val;
3411
3412 /*
3413 * If constant argument and the per-element expression is
3414 * immutable, we can simplify the whole thing to a constant.
3415 * Exception: although contain_mutable_functions considers
3416 * CoerceToDomain immutable for historical reasons, let's not
3417 * do so here; this ensures coercion to an array-over-domain
3418 * does not apply the domain's constraints until runtime.
3419 */
3420 if (ac->arg && IsA(ac->arg, Const) &&
3421 ac->elemexpr && !IsA(ac->elemexpr, CoerceToDomain) &&
3422 !contain_mutable_functions((Node *) ac->elemexpr))
3423 return ece_evaluate_expr(ac);
3424
3425 return (Node *) ac;
3426 }
3427 case T_CollateExpr:
3428 {
3429 /*
3430 * We replace CollateExpr with RelabelType, so as to improve
3431 * uniformity of expression representation and thus simplify
3432 * comparison of expressions. Hence this looks very nearly
3433 * the same as the RelabelType case, and we can apply the same
3434 * optimizations to avoid unnecessary RelabelTypes.
3435 */
3436 CollateExpr *collate = (CollateExpr *) node;
3437 Node *arg;
3438
3439 /* Simplify the input ... */
3441 context);
3442 /* ... and attach a new RelabelType node, if needed */
3443 return applyRelabelType(arg,
3444 exprType(arg),
3445 exprTypmod(arg),
3446 collate->collOid,
3448 collate->location,
3449 true);
3450 }
3451 case T_CaseExpr:
3452 {
3453 /*----------
3454 * CASE expressions can be simplified if there are constant
3455 * condition clauses:
3456 * FALSE (or NULL): drop the alternative
3457 * TRUE: drop all remaining alternatives
3458 * If the first non-FALSE alternative is a constant TRUE,
3459 * we can simplify the entire CASE to that alternative's
3460 * expression. If there are no non-FALSE alternatives,
3461 * we simplify the entire CASE to the default result (ELSE).
3462 *
3463 * If we have a simple-form CASE with constant test
3464 * expression, we substitute the constant value for contained
3465 * CaseTestExpr placeholder nodes, so that we have the
3466 * opportunity to reduce constant test conditions. For
3467 * example this allows
3468 * CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
3469 * to reduce to 1 rather than drawing a divide-by-0 error.
3470 * Note that when the test expression is constant, we don't
3471 * have to include it in the resulting CASE; for example
3472 * CASE 0 WHEN x THEN y ELSE z END
3473 * is transformed by the parser to
3474 * CASE 0 WHEN CaseTestExpr = x THEN y ELSE z END
3475 * which we can simplify to
3476 * CASE WHEN 0 = x THEN y ELSE z END
3477 * It is not necessary for the executor to evaluate the "arg"
3478 * expression when executing the CASE, since any contained
3479 * CaseTestExprs that might have referred to it will have been
3480 * replaced by the constant.
3481 *----------
3482 */
3483 CaseExpr *caseexpr = (CaseExpr *) node;
3486 Node *newarg;
3487 List *newargs;
3488 bool const_true_cond;
3489 Node *defresult = NULL;
3490 ListCell *arg;
3491
3492 /* Simplify the test expression, if any */
3494 context);
3495
3496 /* Set up for contained CaseTestExpr nodes */
3497 save_case_val = context->case_val;
3498 if (newarg && IsA(newarg, Const))
3499 {
3500 context->case_val = newarg;
3501 newarg = NULL; /* not needed anymore, see above */
3502 }
3503 else
3504 context->case_val = NULL;
3505
3506 /* Simplify the WHEN clauses */
3507 newargs = NIL;
3508 const_true_cond = false;
3509 foreach(arg, caseexpr->args)
3510 {
3512 Node *casecond;
3514
3515 /* Simplify this alternative's test condition */
3517 context);
3518
3519 /*
3520 * If the test condition is constant FALSE (or NULL), then
3521 * drop this WHEN clause completely, without processing
3522 * the result.
3523 */
3524 if (casecond && IsA(casecond, Const))
3525 {
3527
3528 if (const_input->constisnull ||
3529 !DatumGetBool(const_input->constvalue))
3530 continue; /* drop alternative with FALSE cond */
3531 /* Else it's constant TRUE */
3532 const_true_cond = true;
3533 }
3534
3535 /* Simplify this alternative's result value */
3537 context);
3538
3539 /* If non-constant test condition, emit a new WHEN node */
3540 if (!const_true_cond)
3541 {
3543
3544 newcasewhen->expr = (Expr *) casecond;
3545 newcasewhen->result = (Expr *) caseresult;
3546 newcasewhen->location = oldcasewhen->location;
3548 continue;
3549 }
3550
3551 /*
3552 * Found a TRUE condition, so none of the remaining
3553 * alternatives can be reached. We treat the result as
3554 * the default result.
3555 */
3556 defresult = caseresult;
3557 break;
3558 }
3559
3560 /* Simplify the default result, unless we replaced it above */
3561 if (!const_true_cond)
3562 defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
3563 context);
3564
3565 context->case_val = save_case_val;
3566
3567 /*
3568 * If no non-FALSE alternatives, CASE reduces to the default
3569 * result
3570 */
3571 if (newargs == NIL)
3572 return defresult;
3573 /* Otherwise we need a new CASE node */
3575 newcase->casetype = caseexpr->casetype;
3576 newcase->casecollid = caseexpr->casecollid;
3577 newcase->arg = (Expr *) newarg;
3578 newcase->args = newargs;
3579 newcase->defresult = (Expr *) defresult;
3580 newcase->location = caseexpr->location;
3581 return (Node *) newcase;
3582 }
3583 case T_CaseTestExpr:
3584 {
3585 /*
3586 * If we know a constant test value for the current CASE
3587 * construct, substitute it for the placeholder. Else just
3588 * return the placeholder as-is.
3589 */
3590 if (context->case_val)
3591 return copyObject(context->case_val);
3592 else
3593 return copyObject(node);
3594 }
3595 case T_SubscriptingRef:
3596 case T_ArrayExpr:
3597 case T_RowExpr:
3598 case T_MinMaxExpr:
3599 {
3600 /*
3601 * Generic handling for node types whose own processing is
3602 * known to be immutable, and for which we need no smarts
3603 * beyond "simplify if all inputs are constants".
3604 *
3605 * Treating SubscriptingRef this way assumes that subscripting
3606 * fetch and assignment are both immutable. This constrains
3607 * type-specific subscripting implementations; maybe we should
3608 * relax it someday.
3609 *
3610 * Treating MinMaxExpr this way amounts to assuming that the
3611 * btree comparison function it calls is immutable; see the
3612 * reasoning in contain_mutable_functions_walker.
3613 */
3614
3615 /* Copy the node and const-simplify its arguments */
3616 node = ece_generic_processing(node);
3617 /* If all arguments are Consts, we can fold to a constant */
3618 if (ece_all_arguments_const(node))
3619 return ece_evaluate_expr(node);
3620 return node;
3621 }
3622 case T_CoalesceExpr:
3623 {
3626 List *newargs;
3627 ListCell *arg;
3628
3629 newargs = NIL;
3630 foreach(arg, coalesceexpr->args)
3631 {
3632 Node *e;
3633
3635 context);
3636
3637 /*
3638 * We can remove null constants from the list. For a
3639 * nonnullable expression, if it has not been preceded by
3640 * any non-null-constant expressions then it is the
3641 * result. Otherwise, it's the next argument, but we can
3642 * drop following arguments since they will never be
3643 * reached.
3644 */
3645 if (IsA(e, Const))
3646 {
3647 if (((Const *) e)->constisnull)
3648 continue; /* drop null constant */
3649 if (newargs == NIL)
3650 return e; /* first expr */
3652 break;
3653 }
3654 if (expr_is_nonnullable(context->root, (Expr *) e,
3656 {
3657 if (newargs == NIL)
3658 return e; /* first expr */
3660 break;
3661 }
3662
3664 }
3665
3666 /*
3667 * If all the arguments were constant null, the result is just
3668 * null
3669 */
3670 if (newargs == NIL)
3671 return (Node *) makeNullConst(coalesceexpr->coalescetype,
3672 -1,
3673 coalesceexpr->coalescecollid);
3674
3675 /*
3676 * If there's exactly one surviving argument, we no longer
3677 * need COALESCE at all: the result is that argument
3678 */
3679 if (list_length(newargs) == 1)
3680 return (Node *) linitial(newargs);
3681
3683 newcoalesce->coalescetype = coalesceexpr->coalescetype;
3684 newcoalesce->coalescecollid = coalesceexpr->coalescecollid;
3685 newcoalesce->args = newargs;
3686 newcoalesce->location = coalesceexpr->location;
3687 return (Node *) newcoalesce;
3688 }
3689 case T_SQLValueFunction:
3690 {
3691 /*
3692 * All variants of SQLValueFunction are stable, so if we are
3693 * estimating the expression's value, we should evaluate the
3694 * current function value. Otherwise just copy.
3695 */
3696 SQLValueFunction *svf = (SQLValueFunction *) node;
3697
3698 if (context->estimate)
3699 return (Node *) evaluate_expr((Expr *) svf,
3700 svf->type,
3701 svf->typmod,
3702 InvalidOid);
3703 else
3704 return copyObject((Node *) svf);
3705 }
3706 case T_FieldSelect:
3707 {
3708 /*
3709 * We can optimize field selection from a whole-row Var into a
3710 * simple Var. (This case won't be generated directly by the
3711 * parser, because ParseComplexProjection short-circuits it.
3712 * But it can arise while simplifying functions.) Also, we
3713 * can optimize field selection from a RowExpr construct, or
3714 * of course from a constant.
3715 *
3716 * However, replacing a whole-row Var in this way has a
3717 * pitfall: if we've already built the rel targetlist for the
3718 * source relation, then the whole-row Var is scheduled to be
3719 * produced by the relation scan, but the simple Var probably
3720 * isn't, which will lead to a failure in setrefs.c. This is
3721 * not a problem when handling simple single-level queries, in
3722 * which expression simplification always happens first. It
3723 * is a risk for lateral references from subqueries, though.
3724 * To avoid such failures, don't optimize uplevel references.
3725 *
3726 * We must also check that the declared type of the field is
3727 * still the same as when the FieldSelect was created --- this
3728 * can change if someone did ALTER COLUMN TYPE on the rowtype.
3729 * If it isn't, we skip the optimization; the case will
3730 * probably fail at runtime, but that's not our problem here.
3731 */
3732 FieldSelect *fselect = (FieldSelect *) node;
3734 Node *arg;
3735
3737 context);
3738 if (arg && IsA(arg, Var) &&
3739 ((Var *) arg)->varattno == InvalidAttrNumber &&
3740 ((Var *) arg)->varlevelsup == 0)
3741 {
3742 if (rowtype_field_matches(((Var *) arg)->vartype,
3743 fselect->fieldnum,
3744 fselect->resulttype,
3745 fselect->resulttypmod,
3746 fselect->resultcollid))
3747 {
3748 Var *newvar;
3749
3750 newvar = makeVar(((Var *) arg)->varno,
3751 fselect->fieldnum,
3752 fselect->resulttype,
3753 fselect->resulttypmod,
3754 fselect->resultcollid,
3755 ((Var *) arg)->varlevelsup);
3756 /* New Var has same OLD/NEW returning as old one */
3757 newvar->varreturningtype = ((Var *) arg)->varreturningtype;
3758 /* New Var is nullable by same rels as the old one */
3759 newvar->varnullingrels = ((Var *) arg)->varnullingrels;
3760 return (Node *) newvar;
3761 }
3762 }
3763 if (arg && IsA(arg, RowExpr))
3764 {
3765 RowExpr *rowexpr = (RowExpr *) arg;
3766
3767 if (fselect->fieldnum > 0 &&
3768 fselect->fieldnum <= list_length(rowexpr->args))
3769 {
3770 Node *fld = (Node *) list_nth(rowexpr->args,
3771 fselect->fieldnum - 1);
3772
3773 if (rowtype_field_matches(rowexpr->row_typeid,
3774 fselect->fieldnum,
3775 fselect->resulttype,
3776 fselect->resulttypmod,
3777 fselect->resultcollid) &&
3778 fselect->resulttype == exprType(fld) &&
3779 fselect->resulttypmod == exprTypmod(fld) &&
3780 fselect->resultcollid == exprCollation(fld))
3781 return fld;
3782 }
3783 }
3785 newfselect->arg = (Expr *) arg;
3786 newfselect->fieldnum = fselect->fieldnum;
3787 newfselect->resulttype = fselect->resulttype;
3788 newfselect->resulttypmod = fselect->resulttypmod;
3789 newfselect->resultcollid = fselect->resultcollid;
3790 if (arg && IsA(arg, Const))
3791 {
3792 Const *con = (Const *) arg;
3793
3795 newfselect->fieldnum,
3796 newfselect->resulttype,
3797 newfselect->resulttypmod,
3798 newfselect->resultcollid))
3800 }
3801 return (Node *) newfselect;
3802 }
3803 case T_NullTest:
3804 {
3805 NullTest *ntest = (NullTest *) node;
3807 Node *arg;
3808
3810 context);
3811 if (ntest->argisrow && arg && IsA(arg, RowExpr))
3812 {
3813 /*
3814 * We break ROW(...) IS [NOT] NULL into separate tests on
3815 * its component fields. This form is usually more
3816 * efficient to evaluate, as well as being more amenable
3817 * to optimization.
3818 */
3819 RowExpr *rarg = (RowExpr *) arg;
3820 List *newargs = NIL;
3821 ListCell *l;
3822
3823 foreach(l, rarg->args)
3824 {
3825 Node *relem = (Node *) lfirst(l);
3826
3827 /*
3828 * A constant field refutes the whole NullTest if it's
3829 * of the wrong nullness; else we can discard it.
3830 */
3831 if (relem && IsA(relem, Const))
3832 {
3833 Const *carg = (Const *) relem;
3834
3835 if (carg->constisnull ?
3836 (ntest->nulltesttype == IS_NOT_NULL) :
3837 (ntest->nulltesttype == IS_NULL))
3838 return makeBoolConst(false, false);
3839 continue;
3840 }
3841
3842 /*
3843 * A proven non-nullable field refutes the whole
3844 * NullTest if the test is IS NULL; else we can
3845 * discard it.
3846 */
3847 if (relem &&
3848 expr_is_nonnullable(context->root, (Expr *) relem,
3850 {
3851 if (ntest->nulltesttype == IS_NULL)
3852 return makeBoolConst(false, false);
3853 continue;
3854 }
3855
3856 /*
3857 * Else, make a scalar (argisrow == false) NullTest
3858 * for this field. Scalar semantics are required
3859 * because IS [NOT] NULL doesn't recurse; see comments
3860 * in ExecEvalRowNullInt().
3861 */
3863 newntest->arg = (Expr *) relem;
3864 newntest->nulltesttype = ntest->nulltesttype;
3865 newntest->argisrow = false;
3866 newntest->location = ntest->location;
3868 }
3869 /* If all the inputs were constants, result is TRUE */
3870 if (newargs == NIL)
3871 return makeBoolConst(true, false);
3872 /* If only one nonconst input, it's the result */
3873 if (list_length(newargs) == 1)
3874 return (Node *) linitial(newargs);
3875 /* Else we need an AND node */
3876 return (Node *) make_andclause(newargs);
3877 }
3878 if (!ntest->argisrow && arg && IsA(arg, Const))
3879 {
3880 Const *carg = (Const *) arg;
3881 bool result;
3882
3883 switch (ntest->nulltesttype)
3884 {
3885 case IS_NULL:
3886 result = carg->constisnull;
3887 break;
3888 case IS_NOT_NULL:
3889 result = !carg->constisnull;
3890 break;
3891 default:
3892 elog(ERROR, "unrecognized nulltesttype: %d",
3893 (int) ntest->nulltesttype);
3894 result = false; /* keep compiler quiet */
3895 break;
3896 }
3897
3898 return makeBoolConst(result, false);
3899 }
3900 if (!ntest->argisrow && arg &&
3901 expr_is_nonnullable(context->root, (Expr *) arg,
3903 {
3904 bool result;
3905
3906 switch (ntest->nulltesttype)
3907 {
3908 case IS_NULL:
3909 result = false;
3910 break;
3911 case IS_NOT_NULL:
3912 result = true;
3913 break;
3914 default:
3915 elog(ERROR, "unrecognized nulltesttype: %d",
3916 (int) ntest->nulltesttype);
3917 result = false; /* keep compiler quiet */
3918 break;
3919 }
3920
3921 return makeBoolConst(result, false);
3922 }
3923
3925 newntest->arg = (Expr *) arg;
3926 newntest->nulltesttype = ntest->nulltesttype;
3927 newntest->argisrow = ntest->argisrow;
3928 newntest->location = ntest->location;
3929 return (Node *) newntest;
3930 }
3931 case T_BooleanTest:
3932 {
3933 /*
3934 * This case could be folded into the generic handling used
3935 * for ArrayExpr etc. But because the simplification logic is
3936 * so trivial, applying evaluate_expr() to perform it would be
3937 * a heavy overhead. BooleanTest is probably common enough to
3938 * justify keeping this bespoke implementation.
3939 */
3940 BooleanTest *btest = (BooleanTest *) node;
3942 Node *arg;
3943
3945 context);
3946 if (arg && IsA(arg, Const))
3947 {
3948 /*
3949 * If arg is Const, simplify to constant.
3950 */
3951 Const *carg = (Const *) arg;
3952 bool result;
3953
3954 switch (btest->booltesttype)
3955 {
3956 case IS_TRUE:
3957 result = (!carg->constisnull &&
3958 DatumGetBool(carg->constvalue));
3959 break;
3960 case IS_NOT_TRUE:
3961 result = (carg->constisnull ||
3962 !DatumGetBool(carg->constvalue));
3963 break;
3964 case IS_FALSE:
3965 result = (!carg->constisnull &&
3966 !DatumGetBool(carg->constvalue));
3967 break;
3968 case IS_NOT_FALSE:
3969 result = (carg->constisnull ||
3970 DatumGetBool(carg->constvalue));
3971 break;
3972 case IS_UNKNOWN:
3973 result = carg->constisnull;
3974 break;
3975 case IS_NOT_UNKNOWN:
3976 result = !carg->constisnull;
3977 break;
3978 default:
3979 elog(ERROR, "unrecognized booltesttype: %d",
3980 (int) btest->booltesttype);
3981 result = false; /* keep compiler quiet */
3982 break;
3983 }
3984
3985 return makeBoolConst(result, false);
3986 }
3987 if (arg &&
3988 expr_is_nonnullable(context->root, (Expr *) arg,
3990 {
3991 /*
3992 * If arg is proven non-nullable, simplify to boolean
3993 * expression or constant.
3994 */
3995 switch (btest->booltesttype)
3996 {
3997 case IS_TRUE:
3998 case IS_NOT_FALSE:
3999 return arg;
4000
4001 case IS_FALSE:
4002 case IS_NOT_TRUE:
4003 return (Node *) make_notclause((Expr *) arg);
4004
4005 case IS_UNKNOWN:
4006 return makeBoolConst(false, false);
4007
4008 case IS_NOT_UNKNOWN:
4009 return makeBoolConst(true, false);
4010
4011 default:
4012 elog(ERROR, "unrecognized booltesttype: %d",
4013 (int) btest->booltesttype);
4014 break;
4015 }
4016 }
4017
4019 newbtest->arg = (Expr *) arg;
4020 newbtest->booltesttype = btest->booltesttype;
4021 newbtest->location = btest->location;
4022 return (Node *) newbtest;
4023 }
4024 case T_CoerceToDomain:
4025 {
4026 /*
4027 * If the domain currently has no constraints, we replace the
4028 * CoerceToDomain node with a simple RelabelType, which is
4029 * both far faster to execute and more amenable to later
4030 * optimization. We must then mark the plan as needing to be
4031 * rebuilt if the domain's constraints change.
4032 *
4033 * Also, in estimation mode, always replace CoerceToDomain
4034 * nodes, effectively assuming that the coercion will succeed.
4035 */
4038 Node *arg;
4039
4041 context);
4042 if (context->estimate ||
4043 !DomainHasConstraints(cdomain->resulttype, NULL))
4044 {
4045 /* Record dependency, if this isn't estimation mode */
4046 if (context->root && !context->estimate)
4047 record_plan_type_dependency(context->root,
4048 cdomain->resulttype);
4049
4050 /* Generate RelabelType to substitute for CoerceToDomain */
4051 return applyRelabelType(arg,
4052 cdomain->resulttype,
4053 cdomain->resulttypmod,
4054 cdomain->resultcollid,
4055 cdomain->coercionformat,
4056 cdomain->location,
4057 true);
4058 }
4059
4061 newcdomain->arg = (Expr *) arg;
4062 newcdomain->resulttype = cdomain->resulttype;
4063 newcdomain->resulttypmod = cdomain->resulttypmod;
4064 newcdomain->resultcollid = cdomain->resultcollid;
4065 newcdomain->coercionformat = cdomain->coercionformat;
4066 newcdomain->location = cdomain->location;
4067 return (Node *) newcdomain;
4068 }
4069 case T_PlaceHolderVar:
4070
4071 /*
4072 * In estimation mode, just strip the PlaceHolderVar node
4073 * altogether; this amounts to estimating that the contained value
4074 * won't be forced to null by an outer join. In regular mode we
4075 * just use the default behavior (ie, simplify the expression but
4076 * leave the PlaceHolderVar node intact).
4077 */
4078 if (context->estimate)
4079 {
4080 PlaceHolderVar *phv = (PlaceHolderVar *) node;
4081
4082 return eval_const_expressions_mutator((Node *) phv->phexpr,
4083 context);
4084 }
4085 break;
4087 {
4089 Node *arg;
4091
4093 context);
4094
4096 newcre->resulttype = cre->resulttype;
4097 newcre->convertformat = cre->convertformat;
4098 newcre->location = cre->location;
4099
4100 /*
4101 * In case of a nested ConvertRowtypeExpr, we can convert the
4102 * leaf row directly to the topmost row format without any
4103 * intermediate conversions. (This works because
4104 * ConvertRowtypeExpr is used only for child->parent
4105 * conversion in inheritance trees, which works by exact match
4106 * of column name, and a column absent in an intermediate
4107 * result can't be present in the final result.)
4108 *
4109 * No need to check more than one level deep, because the
4110 * above recursion will have flattened anything else.
4111 */
4112 if (arg != NULL && IsA(arg, ConvertRowtypeExpr))
4113 {
4115
4116 arg = (Node *) argcre->arg;
4117
4118 /*
4119 * Make sure an outer implicit conversion can't hide an
4120 * inner explicit one.
4121 */
4122 if (newcre->convertformat == COERCE_IMPLICIT_CAST)
4123 newcre->convertformat = argcre->convertformat;
4124 }
4125
4126 newcre->arg = (Expr *) arg;
4127
4128 if (arg != NULL && IsA(arg, Const))
4129 return ece_evaluate_expr((Node *) newcre);
4130 return (Node *) newcre;
4131 }
4132 default:
4133 break;
4134 }
4135
4136 /*
4137 * For any node type not handled above, copy the node unchanged but
4138 * const-simplify its subexpressions. This is the correct thing for node
4139 * types whose behavior might change between planning and execution, such
4140 * as CurrentOfExpr. It's also a safe default for new node types not
4141 * known to this routine.
4142 */
4143 return ece_generic_processing(node);
4144}
4145
4146/*
4147 * Subroutine for eval_const_expressions: check for non-Const nodes.
4148 *
4149 * We can abort recursion immediately on finding a non-Const node. This is
4150 * critical for performance, else eval_const_expressions_mutator would take
4151 * O(N^2) time on non-simplifiable trees. However, we do need to descend
4152 * into List nodes since expression_tree_walker sometimes invokes the walker
4153 * function directly on List subtrees.
4154 */
4155static bool
4156contain_non_const_walker(Node *node, void *context)
4157{
4158 if (node == NULL)
4159 return false;
4160 if (IsA(node, Const))
4161 return false;
4162 if (IsA(node, List))
4163 return expression_tree_walker(node, contain_non_const_walker, context);
4164 /* Otherwise, abort the tree traversal and return true */
4165 return true;
4166}
4167
4168/*
4169 * Subroutine for eval_const_expressions: check if a function is OK to evaluate
4170 */
4171static bool
4173{
4174 char provolatile = func_volatile(funcid);
4175
4176 /*
4177 * Ordinarily we are only allowed to simplify immutable functions. But for
4178 * purposes of estimation, we consider it okay to simplify functions that
4179 * are merely stable; the risk that the result might change from planning
4180 * time to execution time is worth taking in preference to not being able
4181 * to estimate the value at all.
4182 */
4184 return true;
4185 if (context->estimate && provolatile == PROVOLATILE_STABLE)
4186 return true;
4187 return false;
4188}
4189
4190/*
4191 * Subroutine for eval_const_expressions: process arguments of an OR clause
4192 *
4193 * This includes flattening of nested ORs as well as recursion to
4194 * eval_const_expressions to simplify the OR arguments.
4195 *
4196 * After simplification, OR arguments are handled as follows:
4197 * non constant: keep
4198 * FALSE: drop (does not affect result)
4199 * TRUE: force result to TRUE
4200 * NULL: keep only one
4201 * We must keep one NULL input because OR expressions evaluate to NULL when no
4202 * input is TRUE and at least one is NULL. We don't actually include the NULL
4203 * here, that's supposed to be done by the caller.
4204 *
4205 * The output arguments *haveNull and *forceTrue must be initialized false
4206 * by the caller. They will be set true if a NULL constant or TRUE constant,
4207 * respectively, is detected anywhere in the argument list.
4208 */
4209static List *
4212 bool *haveNull, bool *forceTrue)
4213{
4214 List *newargs = NIL;
4216
4217 /*
4218 * We want to ensure that any OR immediately beneath another OR gets
4219 * flattened into a single OR-list, so as to simplify later reasoning.
4220 *
4221 * To avoid stack overflow from recursion of eval_const_expressions, we
4222 * resort to some tenseness here: we keep a list of not-yet-processed
4223 * inputs, and handle flattening of nested ORs by prepending to the to-do
4224 * list instead of recursing. Now that the parser generates N-argument
4225 * ORs from simple lists, this complexity is probably less necessary than
4226 * it once was, but we might as well keep the logic.
4227 */
4229 while (unprocessed_args)
4230 {
4232
4234
4235 /* flatten nested ORs as per above comment */
4236 if (is_orclause(arg))
4237 {
4238 List *subargs = ((BoolExpr *) arg)->args;
4240
4242 /* perhaps-overly-tense code to avoid leaking old lists */
4244 continue;
4245 }
4246
4247 /* If it's not an OR, simplify it */
4249
4250 /*
4251 * It is unlikely but not impossible for simplification of a non-OR
4252 * clause to produce an OR. Recheck, but don't be too tense about it
4253 * since it's not a mainstream case. In particular we don't worry
4254 * about const-simplifying the input twice, nor about list leakage.
4255 */
4256 if (is_orclause(arg))
4257 {
4258 List *subargs = ((BoolExpr *) arg)->args;
4259
4261 continue;
4262 }
4263
4264 /*
4265 * OK, we have a const-simplified non-OR argument. Process it per
4266 * comments above.
4267 */
4268 if (IsA(arg, Const))
4269 {
4270 Const *const_input = (Const *) arg;
4271
4272 if (const_input->constisnull)
4273 *haveNull = true;
4274 else if (DatumGetBool(const_input->constvalue))
4275 {
4276 *forceTrue = true;
4277
4278 /*
4279 * Once we detect a TRUE result we can just exit the loop
4280 * immediately. However, if we ever add a notion of
4281 * non-removable functions, we'd need to keep scanning.
4282 */
4283 return NIL;
4284 }
4285 /* otherwise, we can drop the constant-false input */
4286 continue;
4287 }
4288
4289 /* else emit the simplified arg into the result list */
4291 }
4292
4293 return newargs;
4294}
4295
4296/*
4297 * Subroutine for eval_const_expressions: process arguments of an AND clause
4298 *
4299 * This includes flattening of nested ANDs as well as recursion to
4300 * eval_const_expressions to simplify the AND arguments.
4301 *
4302 * After simplification, AND arguments are handled as follows:
4303 * non constant: keep
4304 * TRUE: drop (does not affect result)
4305 * FALSE: force result to FALSE
4306 * NULL: keep only one
4307 * We must keep one NULL input because AND expressions evaluate to NULL when
4308 * no input is FALSE and at least one is NULL. We don't actually include the
4309 * NULL here, that's supposed to be done by the caller.
4310 *
4311 * The output arguments *haveNull and *forceFalse must be initialized false
4312 * by the caller. They will be set true if a null constant or false constant,
4313 * respectively, is detected anywhere in the argument list.
4314 */
4315static List *
4318 bool *haveNull, bool *forceFalse)
4319{
4320 List *newargs = NIL;
4322
4323 /* See comments in simplify_or_arguments */
4325 while (unprocessed_args)
4326 {
4328
4330
4331 /* flatten nested ANDs as per above comment */
4332 if (is_andclause(arg))
4333 {
4334 List *subargs = ((BoolExpr *) arg)->args;
4336
4338 /* perhaps-overly-tense code to avoid leaking old lists */
4340 continue;
4341 }
4342
4343 /* If it's not an AND, simplify it */
4345
4346 /*
4347 * It is unlikely but not impossible for simplification of a non-AND
4348 * clause to produce an AND. Recheck, but don't be too tense about it
4349 * since it's not a mainstream case. In particular we don't worry
4350 * about const-simplifying the input twice, nor about list leakage.
4351 */
4352 if (is_andclause(arg))
4353 {
4354 List *subargs = ((BoolExpr *) arg)->args;
4355
4357 continue;
4358 }
4359
4360 /*
4361 * OK, we have a const-simplified non-AND argument. Process it per
4362 * comments above.
4363 */
4364 if (IsA(arg, Const))
4365 {
4366 Const *const_input = (Const *) arg;
4367
4368 if (const_input->constisnull)
4369 *haveNull = true;
4370 else if (!DatumGetBool(const_input->constvalue))
4371 {
4372 *forceFalse = true;
4373
4374 /*
4375 * Once we detect a FALSE result we can just exit the loop
4376 * immediately. However, if we ever add a notion of
4377 * non-removable functions, we'd need to keep scanning.
4378 */
4379 return NIL;
4380 }
4381 /* otherwise, we can drop the constant-true input */
4382 continue;
4383 }
4384
4385 /* else emit the simplified arg into the result list */
4387 }
4388
4389 return newargs;
4390}
4391
4392/*
4393 * Subroutine for eval_const_expressions: try to simplify boolean equality
4394 * or inequality condition
4395 *
4396 * Inputs are the operator OID and the simplified arguments to the operator.
4397 * Returns a simplified expression if successful, or NULL if cannot
4398 * simplify the expression.
4399 *
4400 * The idea here is to reduce "x = true" to "x" and "x = false" to "NOT x",
4401 * or similarly "x <> true" to "NOT x" and "x <> false" to "x".
4402 * This is only marginally useful in itself, but doing it in constant folding
4403 * ensures that we will recognize these forms as being equivalent in, for
4404 * example, partial index matching.
4405 *
4406 * We come here only if simplify_function has failed; therefore we cannot
4407 * see two constant inputs, nor a constant-NULL input.
4408 */
4409static Node *
4411{
4412 Node *leftop;
4413 Node *rightop;
4414
4415 Assert(list_length(args) == 2);
4416 leftop = linitial(args);
4417 rightop = lsecond(args);
4418 if (leftop && IsA(leftop, Const))
4419 {
4420 Assert(!((Const *) leftop)->constisnull);
4421 if (opno == BooleanEqualOperator)
4422 {
4423 if (DatumGetBool(((Const *) leftop)->constvalue))
4424 return rightop; /* true = foo */
4425 else
4426 return negate_clause(rightop); /* false = foo */
4427 }
4428 else
4429 {
4430 if (DatumGetBool(((Const *) leftop)->constvalue))
4431 return negate_clause(rightop); /* true <> foo */
4432 else
4433 return rightop; /* false <> foo */
4434 }
4435 }
4436 if (rightop && IsA(rightop, Const))
4437 {
4439 if (opno == BooleanEqualOperator)
4440 {
4442 return leftop; /* foo = true */
4443 else
4444 return negate_clause(leftop); /* foo = false */
4445 }
4446 else
4447 {
4449 return negate_clause(leftop); /* foo <> true */
4450 else
4451 return leftop; /* foo <> false */
4452 }
4453 }
4454 return NULL;
4455}
4456
4457/*
4458 * Subroutine for eval_const_expressions: try to simplify a function call
4459 * (which might originally have been an operator; we don't care)
4460 *
4461 * Inputs are the function OID, actual result type OID (which is needed for
4462 * polymorphic functions), result typmod, result collation, the input
4463 * collation to use for the function, the original argument list (not
4464 * const-simplified yet, unless process_args is false), and some flags;
4465 * also the context data for eval_const_expressions.
4466 *
4467 * Returns a simplified expression if successful, or NULL if cannot
4468 * simplify the function call.
4469 *
4470 * This function is also responsible for converting named-notation argument
4471 * lists into positional notation and/or adding any needed default argument
4472 * expressions; which is a bit grotty, but it avoids extra fetches of the
4473 * function's pg_proc tuple. For this reason, the args list is
4474 * pass-by-reference. Conversion and const-simplification of the args list
4475 * will be done even if simplification of the function call itself is not
4476 * possible.
4477 */
4478static Expr *
4479simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
4481 bool funcvariadic, bool process_args, bool allow_non_const,
4483{
4484 List *args = *args_p;
4487 Expr *newexpr;
4488
4489 /*
4490 * We have three strategies for simplification: execute the function to
4491 * deliver a constant result, use a transform function to generate a
4492 * substitute node tree, or expand in-line the body of the function
4493 * definition (which only works for simple SQL-language functions, but
4494 * that is a common case). Each case needs access to the function's
4495 * pg_proc tuple, so fetch it just once.
4496 *
4497 * Note: the allow_non_const flag suppresses both the second and third
4498 * strategies; so if !allow_non_const, simplify_function can only return a
4499 * Const or NULL. Argument-list rewriting happens anyway, though.
4500 */
4503 elog(ERROR, "cache lookup failed for function %u", funcid);
4505
4506 /*
4507 * Process the function arguments, unless the caller did it already.
4508 *
4509 * Here we must deal with named or defaulted arguments, and then
4510 * recursively apply eval_const_expressions to the whole argument list.
4511 */
4512 if (process_args)
4513 {
4514 args = expand_function_arguments(args, false, result_type, func_tuple);
4517 context);
4518 /* Argument processing done, give it back to the caller */
4519 *args_p = args;
4520 }
4521
4522 /* Now attempt simplification of the function call proper. */
4523
4524 newexpr = evaluate_function(funcid, result_type, result_typmod,
4526 args, funcvariadic,
4527 func_tuple, context);
4528
4529 if (!newexpr && allow_non_const && OidIsValid(func_form->prosupport))
4530 {
4531 /*
4532 * Build a SupportRequestSimplify node to pass to the support
4533 * function, pointing to a dummy FuncExpr node containing the
4534 * simplified arg list. We use this approach to present a uniform
4535 * interface to the support function regardless of how the target
4536 * function is actually being invoked.
4537 */
4540
4541 fexpr.xpr.type = T_FuncExpr;
4542 fexpr.funcid = funcid;
4543 fexpr.funcresulttype = result_type;
4544 fexpr.funcretset = func_form->proretset;
4545 fexpr.funcvariadic = funcvariadic;
4546 fexpr.funcformat = COERCE_EXPLICIT_CALL;
4547 fexpr.funccollid = result_collid;
4548 fexpr.inputcollid = input_collid;
4549 fexpr.args = args;
4550 fexpr.location = -1;
4551
4553 req.root = context->root;
4554 req.fcall = &fexpr;
4555
4556 newexpr = (Expr *)
4558 PointerGetDatum(&req)));
4559
4560 /* catch a possible API misunderstanding */
4561 Assert(newexpr != (Expr *) &fexpr);
4562 }
4563
4564 if (!newexpr && allow_non_const)
4565 newexpr = inline_function(funcid, result_type, result_collid,
4567 func_tuple, context);
4568
4570
4571 return newexpr;
4572}
4573
4574/*
4575 * simplify_aggref
4576 * Call the Aggref.aggfnoid's prosupport function to allow it to
4577 * determine if simplification of the Aggref is possible. Returns the
4578 * newly simplified node if conversion took place; otherwise, returns the
4579 * original Aggref.
4580 *
4581 * See SupportRequestSimplifyAggref comments in supportnodes.h for further
4582 * details.
4583 */
4584static Node *
4586{
4588
4590 {
4592 Node *newnode;
4593
4594 /*
4595 * Build a SupportRequestSimplifyAggref node to pass to the support
4596 * function.
4597 */
4599 req.root = context->root;
4600 req.aggref = aggref;
4601
4603 PointerGetDatum(&req)));
4604
4605 /*
4606 * We expect the support function to return either a new Node or NULL
4607 * (when simplification isn't possible).
4608 */
4609 Assert(newnode != (Node *) aggref || newnode == NULL);
4610
4611 if (newnode != NULL)
4612 return newnode;
4613 }
4614
4615 return (Node *) aggref;
4616}
4617
4618/*
4619 * var_is_nonnullable: check to see if the Var cannot be NULL
4620 *
4621 * If the Var is defined NOT NULL and meanwhile is not nulled by any outer
4622 * joins or grouping sets, then we can know that it cannot be NULL.
4623 *
4624 * "source" specifies where we should look for NOT NULL proofs.
4625 */
4626bool
4628{
4629 Assert(IsA(var, Var));
4630
4631 /* skip upper-level Vars */
4632 if (var->varlevelsup != 0)
4633 return false;
4634
4635 /* could the Var be nulled by any outer joins or grouping sets? */
4636 if (!bms_is_empty(var->varnullingrels))
4637 return false;
4638
4639 /*
4640 * If the Var has a non-default returning type, it could be NULL
4641 * regardless of any NOT NULL constraint. For example, OLD.col is NULL
4642 * for INSERT, and NEW.col is NULL for DELETE.
4643 */
4645 return false;
4646
4647 /* system columns cannot be NULL */
4648 if (var->varattno < 0)
4649 return true;
4650
4651 /* we don't trust whole-row Vars */
4652 if (var->varattno == 0)
4653 return false;
4654
4655 /* Check if the Var is defined as NOT NULL. */
4656 switch (source)
4657 {
4659 {
4660 /*
4661 * We retrieve the column NOT NULL constraint information from
4662 * the corresponding RelOptInfo.
4663 */
4664 RelOptInfo *rel;
4665 Bitmapset *notnullattnums;
4666
4667 rel = find_base_rel(root, var->varno);
4668 notnullattnums = rel->notnullattnums;
4669
4670 return bms_is_member(var->varattno, notnullattnums);
4671 }
4673 {
4674 /*
4675 * We retrieve the column NOT NULL constraint information from
4676 * the hash table.
4677 */
4679 Bitmapset *notnullattnums;
4680
4681 rte = planner_rt_fetch(var->varno, root);
4682
4683 /* We can only reason about ordinary relations */
4684 if (rte->rtekind != RTE_RELATION)
4685 return false;
4686
4687 /*
4688 * We must skip inheritance parent tables, as some child
4689 * tables may have a NOT NULL constraint for a column while
4690 * others may not. This cannot happen with partitioned
4691 * tables, though.
4692 */
4693 if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
4694 return false;
4695
4696 notnullattnums = find_relation_notnullatts(root, rte->relid);
4697
4698 return bms_is_member(var->varattno, notnullattnums);
4699 }
4701 {
4702 /*
4703 * We check the attnullability field in the tuple descriptor.
4704 * This is necessary rather than checking the attnotnull field
4705 * from the attribute relation, because attnotnull is also set
4706 * for invalid (NOT VALID) NOT NULL constraints, which do not
4707 * guarantee the absence of NULLs.
4708 */
4710 Relation rel;
4711 CompactAttribute *attr;
4712 bool result;
4713
4714 rte = planner_rt_fetch(var->varno, root);
4715
4716 /* We can only reason about ordinary relations */
4717 if (rte->rtekind != RTE_RELATION)
4718 return false;
4719
4720 /*
4721 * We must skip inheritance parent tables, as some child
4722 * tables may have a NOT NULL constraint for a column while
4723 * others may not. This cannot happen with partitioned
4724 * tables, though.
4725 *
4726 * Note that we need to check if the relation actually has any
4727 * children, as we might not have done that yet.
4728 */
4729 if (rte->inh && has_subclass(rte->relid) &&
4730 rte->relkind != RELKIND_PARTITIONED_TABLE)
4731 return false;
4732
4733 /* We need not lock the relation since it was already locked */
4734 rel = table_open(rte->relid, NoLock);
4736 var->varattno - 1);
4738 table_close(rel, NoLock);
4739
4740 return result;
4741 }
4742 default:
4743 elog(ERROR, "unrecognized NotNullSource: %d",
4744 (int) source);
4745 break;
4746 }
4747
4748 return false;
4749}
4750
4751/*
4752 * expr_is_nonnullable: check to see if the Expr cannot be NULL
4753 *
4754 * Returns true iff the given 'expr' cannot produce SQL NULLs.
4755 *
4756 * source: specifies where we should look for NOT NULL proofs for Vars.
4757 * - NOTNULL_SOURCE_RELOPT: Used when RelOptInfos have been generated. We
4758 * retrieve nullability information directly from the RelOptInfo corresponding
4759 * to the Var.
4760 * - NOTNULL_SOURCE_HASHTABLE: Used when RelOptInfos are not yet available,
4761 * but we have already collected relation-level not-null constraints into the
4762 * global hash table.
4763 * - NOTNULL_SOURCE_CATALOG: Used for raw parse trees where neither
4764 * RelOptInfos nor the hash table are available. In this case, we check the
4765 * column's attnullability in the tuple descriptor.
4766 *
4767 * For now, we support only a limited set of expression types. Support for
4768 * additional node types can be added in the future.
4769 */
4770bool
4772{
4773 /* since this function recurses, it could be driven to stack overflow */
4775
4776 switch (nodeTag(expr))
4777 {
4778 case T_Var:
4779 {
4780 if (root)
4781 return var_is_nonnullable(root, (Var *) expr, source);
4782 }
4783 break;
4784 case T_Const:
4785 return !((Const *) expr)->constisnull;
4786 case T_CoalesceExpr:
4787 {
4788 /*
4789 * A CoalesceExpr returns NULL if and only if all its
4790 * arguments are NULL. Therefore, we can determine that a
4791 * CoalesceExpr cannot be NULL if at least one of its
4792 * arguments can be proven non-nullable.
4793 */
4795
4797 {
4799 return true;
4800 }
4801 }
4802 break;
4803 case T_MinMaxExpr:
4804 {
4805 /*
4806 * Like CoalesceExpr, a MinMaxExpr returns NULL only if all
4807 * its arguments evaluate to NULL.
4808 */
4809 MinMaxExpr *minmaxexpr = (MinMaxExpr *) expr;
4810
4812 {
4814 return true;
4815 }
4816 }
4817 break;
4818 case T_CaseExpr:
4819 {
4820 /*
4821 * A CASE expression is non-nullable if all branch results are
4822 * non-nullable. We must also verify that the default result
4823 * (ELSE) exists and is non-nullable.
4824 */
4825 CaseExpr *caseexpr = (CaseExpr *) expr;
4826
4827 /* The default result must be present and non-nullable */
4828 if (caseexpr->defresult == NULL ||
4829 !expr_is_nonnullable(root, caseexpr->defresult, source))
4830 return false;
4831
4832 /* All branch results must be non-nullable */
4834 {
4835 if (!expr_is_nonnullable(root, casewhen->result, source))
4836 return false;
4837 }
4838
4839 return true;
4840 }
4841 break;
4842 case T_ArrayExpr:
4843 {
4844 /*
4845 * An ARRAY[] expression always returns a valid Array object,
4846 * even if it is empty (ARRAY[]) or contains NULLs
4847 * (ARRAY[NULL]). It never evaluates to a SQL NULL.
4848 */
4849 return true;
4850 }
4851 case T_NullTest:
4852 {
4853 /*
4854 * An IS NULL / IS NOT NULL expression always returns a
4855 * boolean value. It never returns SQL NULL.
4856 */
4857 return true;
4858 }
4859 case T_BooleanTest:
4860 {
4861 /*
4862 * A BooleanTest expression always evaluates to a boolean
4863 * value. It never returns SQL NULL.
4864 */
4865 return true;
4866 }
4867 case T_DistinctExpr:
4868 {
4869 /*
4870 * IS DISTINCT FROM never returns NULL, effectively acting as
4871 * though NULL were a normal data value.
4872 */
4873 return true;
4874 }
4875 case T_RelabelType:
4876 {
4877 /*
4878 * RelabelType does not change the nullability of the data.
4879 * The result is non-nullable if and only if the argument is
4880 * non-nullable.
4881 */
4882 return expr_is_nonnullable(root, ((RelabelType *) expr)->arg,
4883 source);
4884 }
4885 default:
4886 break;
4887 }
4888
4889 return false;
4890}
4891
4892/*
4893 * expand_function_arguments: convert named-notation args to positional args
4894 * and/or insert default args, as needed
4895 *
4896 * Returns a possibly-transformed version of the args list.
4897 *
4898 * If include_out_arguments is true, then the args list and the result
4899 * include OUT arguments.
4900 *
4901 * The expected result type of the call must be given, for sanity-checking
4902 * purposes. Also, we ask the caller to provide the function's actual
4903 * pg_proc tuple, not just its OID.
4904 *
4905 * If we need to change anything, the input argument list is copied, not
4906 * modified.
4907 *
4908 * Note: this gets applied to operator argument lists too, even though the
4909 * cases it handles should never occur there. This should be OK since it
4910 * will fall through very quickly if there's nothing to do.
4911 */
4912List *
4914 Oid result_type, HeapTuple func_tuple)
4915{
4917 Oid *proargtypes = funcform->proargtypes.values;
4918 int pronargs = funcform->pronargs;
4919 bool has_named_args = false;
4920 ListCell *lc;
4921
4922 /*
4923 * If we are asked to match to OUT arguments, then use the proallargtypes
4924 * array (which includes those); otherwise use proargtypes (which
4925 * doesn't). Of course, if proallargtypes is null, we always use
4926 * proargtypes. (Fetching proallargtypes is annoyingly expensive
4927 * considering that we may have nothing to do here, but fortunately the
4928 * common case is include_out_arguments == false.)
4929 */
4931 {
4933 bool isNull;
4934
4937 &isNull);
4938 if (!isNull)
4939 {
4941
4942 pronargs = ARR_DIMS(arr)[0];
4943 if (ARR_NDIM(arr) != 1 ||
4944 pronargs < 0 ||
4945 ARR_HASNULL(arr) ||
4946 ARR_ELEMTYPE(arr) != OIDOID)
4947 elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
4948 Assert(pronargs >= funcform->pronargs);
4949 proargtypes = (Oid *) ARR_DATA_PTR(arr);
4950 }
4951 }
4952
4953 /* Do we have any named arguments? */
4954 foreach(lc, args)
4955 {
4956 Node *arg = (Node *) lfirst(lc);
4957
4958 if (IsA(arg, NamedArgExpr))
4959 {
4960 has_named_args = true;
4961 break;
4962 }
4963 }
4964
4965 /* If so, we must apply reorder_function_arguments */
4966 if (has_named_args)
4967 {
4969 /* Recheck argument types and add casts if needed */
4970 recheck_cast_function_args(args, result_type,
4972 func_tuple);
4973 }
4974 else if (list_length(args) < pronargs)
4975 {
4976 /* No named args, but we seem to be short some defaults */
4978 /* Recheck argument types and add casts if needed */
4979 recheck_cast_function_args(args, result_type,
4981 func_tuple);
4982 }
4983
4984 return args;
4985}
4986
4987/*
4988 * reorder_function_arguments: convert named-notation args to positional args
4989 *
4990 * This function also inserts default argument values as needed, since it's
4991 * impossible to form a truly valid positional call without that.
4992 */
4993static List *
4995{
4997 int nargsprovided = list_length(args);
4999 ListCell *lc;
5000 int i;
5001
5004 elog(ERROR, "too many function arguments");
5005 memset(argarray, 0, pronargs * sizeof(Node *));
5006
5007 /* Deconstruct the argument list into an array indexed by argnumber */
5008 i = 0;
5009 foreach(lc, args)
5010 {
5011 Node *arg = (Node *) lfirst(lc);
5012
5013 if (!IsA(arg, NamedArgExpr))
5014 {
5015 /* positional argument, assumed to precede all named args */
5016 Assert(argarray[i] == NULL);
5017 argarray[i++] = arg;
5018 }
5019 else
5020 {
5022
5023 Assert(na->argnumber >= 0 && na->argnumber < pronargs);
5024 Assert(argarray[na->argnumber] == NULL);
5025 argarray[na->argnumber] = (Node *) na->arg;
5026 }
5027 }
5028
5029 /*
5030 * Fetch default expressions, if needed, and insert into array at proper
5031 * locations (they aren't necessarily consecutive or all used)
5032 */
5033 if (nargsprovided < pronargs)
5034 {
5036
5037 i = pronargs - funcform->pronargdefaults;
5038 foreach(lc, defaults)
5039 {
5040 if (argarray[i] == NULL)
5041 argarray[i] = (Node *) lfirst(lc);
5042 i++;
5043 }
5044 }
5045
5046 /* Now reconstruct the args list in proper order */
5047 args = NIL;
5048 for (i = 0; i < pronargs; i++)
5049 {
5050 Assert(argarray[i] != NULL);
5051 args = lappend(args, argarray[i]);
5052 }
5053
5054 return args;
5055}
5056
5057/*
5058 * add_function_defaults: add missing function arguments from its defaults
5059 *
5060 * This is used only when the argument list was positional to begin with,
5061 * and so we know we just need to add defaults at the end.
5062 */
5063static List *
5065{
5066 int nargsprovided = list_length(args);
5067 List *defaults;
5068 int ndelete;
5069
5070 /* Get all the default expressions from the pg_proc tuple */
5072
5073 /* Delete any unused defaults from the list */
5074 ndelete = nargsprovided + list_length(defaults) - pronargs;
5075 if (ndelete < 0)
5076 elog(ERROR, "not enough default arguments");
5077 if (ndelete > 0)
5078 defaults = list_delete_first_n(defaults, ndelete);
5079
5080 /* And form the combined argument list, not modifying the input list */
5081 return list_concat_copy(args, defaults);
5082}
5083
5084/*
5085 * fetch_function_defaults: get function's default arguments as expression list
5086 */
5087static List *
5089{
5090 List *defaults;
5092 char *str;
5093
5097 defaults = castNode(List, stringToNode(str));
5098 pfree(str);
5099 return defaults;
5100}
5101
5102/*
5103 * recheck_cast_function_args: recheck function args and typecast as needed
5104 * after adding defaults.
5105 *
5106 * It is possible for some of the defaulted arguments to be polymorphic;
5107 * therefore we can't assume that the default expressions have the correct
5108 * data types already. We have to re-resolve polymorphics and do coercion
5109 * just like the parser did.
5110 *
5111 * This should be a no-op if there are no polymorphic arguments,
5112 * but we do it anyway to be sure.
5113 *
5114 * Note: if any casts are needed, the args list is modified in-place;
5115 * caller should have already copied the list structure.
5116 */
5117static void
5118recheck_cast_function_args(List *args, Oid result_type,
5119 Oid *proargtypes, int pronargs,
5121{
5123 int nargs;
5126 Oid rettype;
5127 ListCell *lc;
5128
5129 if (list_length(args) > FUNC_MAX_ARGS)
5130 elog(ERROR, "too many function arguments");
5131 nargs = 0;
5132 foreach(lc, args)
5133 {
5134 actual_arg_types[nargs++] = exprType((Node *) lfirst(lc));
5135 }
5136 Assert(nargs == pronargs);
5140 nargs,
5141 funcform->prorettype,
5142 false);
5143 /* let's just check we got the same answer as the parser did ... */
5144 if (rettype != result_type)
5145 elog(ERROR, "function's resolved result type changed during planning");
5146
5147 /* perform any necessary typecasting of arguments */
5149}
5150
5151/*
5152 * evaluate_function: try to pre-evaluate a function call
5153 *
5154 * We can do this if the function is strict and has any constant-null inputs
5155 * (just return a null constant), or if the function is immutable and has all
5156 * constant inputs (call it and return the result as a Const node). In
5157 * estimation mode we are willing to pre-evaluate stable functions too.
5158 *
5159 * Returns a simplified expression if successful, or NULL if cannot
5160 * simplify the function.
5161 */
5162static Expr *
5163evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
5165 bool funcvariadic,
5168{
5170 bool has_nonconst_input = false;
5171 bool has_null_input = false;
5172 ListCell *arg;
5174
5175 /*
5176 * Can't simplify if it returns a set.
5177 */
5178 if (funcform->proretset)
5179 return NULL;
5180
5181 /*
5182 * Can't simplify if it returns RECORD. The immediate problem is that it
5183 * will be needing an expected tupdesc which we can't supply here.
5184 *
5185 * In the case where it has OUT parameters, we could build an expected
5186 * tupdesc from those, but there may be other gotchas lurking. In
5187 * particular, if the function were to return NULL, we would produce a
5188 * null constant with no remaining indication of which concrete record
5189 * type it is. For now, seems best to leave the function call unreduced.
5190 */
5191 if (funcform->prorettype == RECORDOID)
5192 return NULL;
5193
5194 /*
5195 * Check for constant inputs and especially constant-NULL inputs.
5196 */
5197 foreach(arg, args)
5198 {
5199 if (IsA(lfirst(arg), Const))
5201 else
5202 has_nonconst_input = true;
5203 }
5204
5205 /*
5206 * If the function is strict and has a constant-NULL input, it will never
5207 * be called at all, so we can replace the call by a NULL constant, even
5208 * if there are other inputs that aren't constant, and even if the
5209 * function is not otherwise immutable.
5210 */
5211 if (funcform->proisstrict && has_null_input)
5212 return (Expr *) makeNullConst(result_type, result_typmod,
5214
5215 /*
5216 * Otherwise, can simplify only if all inputs are constants. (For a
5217 * non-strict function, constant NULL inputs are treated the same as
5218 * constant non-NULL inputs.)
5219 */
5221 return NULL;
5222
5223 /*
5224 * Ordinarily we are only allowed to simplify immutable functions. But for
5225 * purposes of estimation, we consider it okay to simplify functions that
5226 * are merely stable; the risk that the result might change from planning
5227 * time to execution time is worth taking in preference to not being able
5228 * to estimate the value at all.
5229 */
5230 if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
5231 /* okay */ ;
5232 else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
5233 /* okay */ ;
5234 else
5235 return NULL;
5236
5237 /*
5238 * OK, looks like we can simplify this operator/function.
5239 *
5240 * Build a new FuncExpr node containing the already-simplified arguments.
5241 */
5243 newexpr->funcid = funcid;
5244 newexpr->funcresulttype = result_type;
5245 newexpr->funcretset = false;
5246 newexpr->funcvariadic = funcvariadic;
5247 newexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
5248 newexpr->funccollid = result_collid; /* doesn't matter */
5249 newexpr->inputcollid = input_collid;
5250 newexpr->args = args;
5251 newexpr->location = -1;
5252
5253 return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
5255}
5256
5257/*
5258 * inline_function: try to expand a function call inline
5259 *
5260 * If the function is a sufficiently simple SQL-language function
5261 * (just "SELECT expression"), then we can inline it and avoid the rather
5262 * high per-call overhead of SQL functions. Furthermore, this can expose
5263 * opportunities for constant-folding within the function expression.
5264 *
5265 * We have to beware of some special cases however. A directly or
5266 * indirectly recursive function would cause us to recurse forever,
5267 * so we keep track of which functions we are already expanding and
5268 * do not re-expand them. Also, if a parameter is used more than once
5269 * in the SQL-function body, we require it not to contain any volatile
5270 * functions (volatiles might deliver inconsistent answers) nor to be
5271 * unreasonably expensive to evaluate. The expensiveness check not only
5272 * prevents us from doing multiple evaluations of an expensive parameter
5273 * at runtime, but is a safety value to limit growth of an expression due
5274 * to repeated inlining.
5275 *
5276 * We must also beware of changing the volatility or strictness status of
5277 * functions by inlining them.
5278 *
5279 * Also, at the moment we can't inline functions returning RECORD. This
5280 * doesn't work in the general case because it discards information such
5281 * as OUT-parameter declarations.
5282 *
5283 * Also, context-dependent expression nodes in the argument list are trouble.
5284 *
5285 * Returns a simplified expression if successful, or NULL if cannot
5286 * simplify the function.
5287 */
5288static Expr *
5289inline_function(Oid funcid, Oid result_type, Oid result_collid,
5290 Oid input_collid, List *args,
5291 bool funcvariadic,
5294{
5296 char *src;
5297 Datum tmp;
5298 bool isNull;
5301 inline_error_callback_arg callback_arg;
5303 FuncExpr *fexpr;
5305 TupleDesc rettupdesc;
5306 ParseState *pstate;
5310 Node *newexpr;
5311 int *usecounts;
5312 ListCell *arg;
5313 int i;
5314
5315 /*
5316 * Forget it if the function is not SQL-language or has other showstopper
5317 * properties. (The prokind and nargs checks are just paranoia.)
5318 */
5319 if (funcform->prolang != SQLlanguageId ||
5320 funcform->prokind != PROKIND_FUNCTION ||
5321 funcform->prosecdef ||
5322 funcform->proretset ||
5323 funcform->prorettype == RECORDOID ||
5325 funcform->pronargs != list_length(args))
5326 return NULL;
5327
5328 /* Check for recursive function, and give up trying to expand if so */
5329 if (list_member_oid(context->active_fns, funcid))
5330 return NULL;
5331
5332 /* Check permission to call function (fail later, if not) */
5334 return NULL;
5335
5336 /* Check whether a plugin wants to hook function entry/exit */
5337 if (FmgrHookIsNeeded(funcid))
5338 return NULL;
5339
5340 /*
5341 * Make a temporary memory context, so that we don't leak all the stuff
5342 * that parsing might create.
5343 */
5345 "inline_function",
5348
5349 /*
5350 * We need a dummy FuncExpr node containing the already-simplified
5351 * arguments. (In some cases we don't really need it, but building it is
5352 * cheap enough that it's not worth contortions to avoid.)
5353 */
5355 fexpr->funcid = funcid;
5356 fexpr->funcresulttype = result_type;
5357 fexpr->funcretset = false;
5358 fexpr->funcvariadic = funcvariadic;
5359 fexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
5360 fexpr->funccollid = result_collid; /* doesn't matter */
5361 fexpr->inputcollid = input_collid;
5362 fexpr->args = args;
5363 fexpr->location = -1;
5364
5365 /* Fetch the function body */
5367 src = TextDatumGetCString(tmp);
5368
5369 /*
5370 * Setup error traceback support for ereport(). This is so that we can
5371 * finger the function that bad information came from.
5372 */
5373 callback_arg.proname = NameStr(funcform->proname);
5374 callback_arg.prosrc = src;
5375
5377 sqlerrcontext.arg = &callback_arg;
5380
5381 /* If we have prosqlbody, pay attention to that not prosrc */
5383 func_tuple,
5385 &isNull);
5386 if (!isNull)
5387 {
5388 Node *n;
5389 List *query_list;
5390
5392 if (IsA(n, List))
5393 query_list = linitial_node(List, castNode(List, n));
5394 else
5395 query_list = list_make1(n);
5396 if (list_length(query_list) != 1)
5397 goto fail;
5398 querytree = linitial(query_list);
5399
5400 /*
5401 * Because we'll insist below that the querytree have an empty rtable
5402 * and no sublinks, it cannot have any relation references that need
5403 * to be locked or rewritten. So we can omit those steps.
5404 */
5405 }
5406 else
5407 {
5408 /* Set up to handle parameters while parsing the function body. */
5410 (Node *) fexpr,
5411 input_collid);
5412
5413 /*
5414 * We just do parsing and parse analysis, not rewriting, because
5415 * rewriting will not affect table-free-SELECT-only queries, which is
5416 * all that we care about. Also, we can punt as soon as we detect
5417 * more than one command in the function body.
5418 */
5421 goto fail;
5422
5423 pstate = make_parsestate(NULL);
5424 pstate->p_sourcetext = src;
5425 sql_fn_parser_setup(pstate, pinfo);
5426
5428
5429 free_parsestate(pstate);
5430 }
5431
5432 /*
5433 * The single command must be a simple "SELECT expression".
5434 *
5435 * Note: if you change the tests involved in this, see also plpgsql's
5436 * exec_simple_check_plan(). That generally needs to have the same idea
5437 * of what's a "simple expression", so that inlining a function that
5438 * previously wasn't inlined won't change plpgsql's conclusion.
5439 */
5440 if (!IsA(querytree, Query) ||
5441 querytree->commandType != CMD_SELECT ||
5442 querytree->hasAggs ||
5443 querytree->hasWindowFuncs ||
5444 querytree->hasTargetSRFs ||
5445 querytree->hasSubLinks ||
5446 querytree->cteList ||
5447 querytree->rtable ||
5448 querytree->jointree->fromlist ||
5449 querytree->jointree->quals ||
5450 querytree->groupClause ||
5451 querytree->groupingSets ||
5452 querytree->havingQual ||
5453 querytree->windowClause ||
5454 querytree->distinctClause ||
5455 querytree->sortClause ||
5456 querytree->limitOffset ||
5457 querytree->limitCount ||
5458 querytree->setOperations ||
5459 list_length(querytree->targetList) != 1)
5460 goto fail;
5461
5462 /* If the function result is composite, resolve it */
5464 NULL,
5465 &rettupdesc);
5466
5467 /*
5468 * Make sure the function (still) returns what it's declared to. This
5469 * will raise an error if wrong, but that's okay since the function would
5470 * fail at runtime anyway. Note that check_sql_fn_retval will also insert
5471 * a coercion if needed to make the tlist expression match the declared
5472 * type of the function.
5473 *
5474 * Note: we do not try this until we have verified that no rewriting was
5475 * needed; that's probably not important, but let's be careful.
5476 */
5479 result_type, rettupdesc,
5480 funcform->prokind,
5481 false))
5482 goto fail; /* reject whole-tuple-result cases */
5483
5484 /*
5485 * Given the tests above, check_sql_fn_retval shouldn't have decided to
5486 * inject a projection step, but let's just make sure.
5487 */
5489 goto fail;
5490
5491 /* Now we can grab the tlist expression */
5492 newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
5493
5494 /*
5495 * If the SQL function returns VOID, we can only inline it if it is a
5496 * SELECT of an expression returning VOID (ie, it's just a redirection to
5497 * another VOID-returning function). In all non-VOID-returning cases,
5498 * check_sql_fn_retval should ensure that newexpr returns the function's
5499 * declared result type, so this test shouldn't fail otherwise; but we may
5500 * as well cope gracefully if it does.
5501 */
5502 if (exprType(newexpr) != result_type)
5503 goto fail;
5504
5505 /*
5506 * Additional validity checks on the expression. It mustn't be more
5507 * volatile than the surrounding function (this is to avoid breaking hacks
5508 * that involve pretending a function is immutable when it really ain't).
5509 * If the surrounding function is declared strict, then the expression
5510 * must contain only strict constructs and must use all of the function
5511 * parameters (this is overkill, but an exact analysis is hard).
5512 */
5513 if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
5515 goto fail;
5516 else if (funcform->provolatile == PROVOLATILE_STABLE &&
5518 goto fail;
5519
5520 if (funcform->proisstrict &&
5522 goto fail;
5523
5524 /*
5525 * If any parameter expression contains a context-dependent node, we can't
5526 * inline, for fear of putting such a node into the wrong context.
5527 */
5529 goto fail;
5530
5531 /*
5532 * We may be able to do it; there are still checks on parameter usage to
5533 * make, but those are most easily done in combination with the actual
5534 * substitution of the inputs. So start building expression with inputs
5535 * substituted.
5536 */
5537 usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
5539 args, usecounts);
5540
5541 /* Now check for parameter usage */
5542 i = 0;
5543 foreach(arg, args)
5544 {
5545 Node *param = lfirst(arg);
5546
5547 if (usecounts[i] == 0)
5548 {
5549 /* Param not used at all: uncool if func is strict */
5550 if (funcform->proisstrict)
5551 goto fail;
5552 }
5553 else if (usecounts[i] != 1)
5554 {
5555 /* Param used multiple times: uncool if expensive or volatile */
5557
5558 /*
5559 * We define "expensive" as "contains any subplan or more than 10
5560 * operators". Note that the subplan search has to be done
5561 * explicitly, since cost_qual_eval() will barf on unplanned
5562 * subselects.
5563 */
5564 if (contain_subplans(param))
5565 goto fail;
5567 if (eval_cost.startup + eval_cost.per_tuple >
5568 10 * cpu_operator_cost)
5569 goto fail;
5570
5571 /*
5572 * Check volatility last since this is more expensive than the
5573 * above tests
5574 */
5575 if (contain_volatile_functions(param))
5576 goto fail;
5577 }
5578 i++;
5579 }
5580
5581 /*
5582 * Whew --- we can make the substitution. Copy the modified expression
5583 * out of the temporary memory context, and clean up.
5584 */
5586
5588
5590
5591 /*
5592 * If the result is of a collatable type, force the result to expose the
5593 * correct collation. In most cases this does not matter, but it's
5594 * possible that the function result is used directly as a sort key or in
5595 * other places where we expect exprCollation() to tell the truth.
5596 */
5598 {
5600
5602 {
5604
5605 newnode->arg = (Expr *) newexpr;
5606 newnode->collOid = result_collid;
5607 newnode->location = -1;
5608
5609 newexpr = (Node *) newnode;
5610 }
5611 }
5612
5613 /*
5614 * Since there is now no trace of the function in the plan tree, we must
5615 * explicitly record the plan's dependency on the function.
5616 */
5617 if (context->root)
5618 record_plan_function_dependency(context->root, funcid);
5619
5620 /*
5621 * Recursively try to simplify the modified expression. Here we must add
5622 * the current function to the context list of active functions.
5623 */
5624 context->active_fns = lappend_oid(context->active_fns, funcid);
5626 context->active_fns = list_delete_last(context->active_fns);
5627
5629
5630 return (Expr *) newexpr;
5631
5632 /* Here if func is not inlinable: release temp memory and return NULL */
5633fail:
5637
5638 return NULL;
5639}
5640
5641/*
5642 * Replace Param nodes by appropriate actual parameters
5643 */
5644static Node *
5645substitute_actual_parameters(Node *expr, int nargs, List *args,
5646 int *usecounts)
5647{
5649
5650 context.nargs = nargs;
5651 context.args = args;
5652 context.usecounts = usecounts;
5653
5654 return substitute_actual_parameters_mutator(expr, &context);
5655}
5656
5657static Node *
5660{
5661 if (node == NULL)
5662 return NULL;
5663 if (IsA(node, Param))
5664 {
5665 Param *param = (Param *) node;
5666
5667 if (param->paramkind != PARAM_EXTERN)
5668 elog(ERROR, "unexpected paramkind: %d", (int) param->paramkind);
5669 if (param->paramid <= 0 || param->paramid > context->nargs)
5670 elog(ERROR, "invalid paramid: %d", param->paramid);
5671
5672 /* Count usage of parameter */
5673 context->usecounts[param->paramid - 1]++;
5674
5675 /* Select the appropriate actual arg and replace the Param with it */
5676 /* We don't need to copy at this time (it'll get done later) */
5677 return list_nth(context->args, param->paramid - 1);
5678 }
5680}
5681
5682/*
5683 * error context callback to let us supply a call-stack traceback
5684 */
5685static void
5687{
5690
5691 /* If it's a syntax error, convert to internal syntax error report */
5693 if (syntaxerrposition > 0)
5694 {
5695 errposition(0);
5697 internalerrquery(callback_arg->prosrc);
5698 }
5699
5700 errcontext("SQL function \"%s\" during inlining", callback_arg->proname);
5701}
5702
5703/*
5704 * evaluate_expr: pre-evaluate a constant expression
5705 *
5706 * We use the executor's routine ExecEvalExpr() to avoid duplication of
5707 * code and ensure we get the same result as the executor would get.
5708 */
5709Expr *
5710evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
5712{
5713 EState *estate;
5714 ExprState *exprstate;
5715 MemoryContext oldcontext;
5717 bool const_is_null;
5719 bool resultTypByVal;
5720
5721 /*
5722 * To use the executor, we need an EState.
5723 */
5724 estate = CreateExecutorState();
5725
5726 /* We can use the estate's working context to avoid memory leaks. */
5727 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
5728
5729 /* Make sure any opfuncids are filled in. */
5730 fix_opfuncids((Node *) expr);
5731
5732 /*
5733 * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
5734 * because it'd result in recursively invoking eval_const_expressions.)
5735 */
5736 exprstate = ExecInitExpr(expr, NULL);
5737
5738 /*
5739 * And evaluate it.
5740 *
5741 * It is OK to use a default econtext because none of the ExecEvalExpr()
5742 * code used in this situation will use econtext. That might seem
5743 * fortuitous, but it's not so unreasonable --- a constant expression does
5744 * not depend on context, by definition, n'est ce pas?
5745 */
5747 GetPerTupleExprContext(estate),
5748 &const_is_null);
5749
5750 /* Get info needed about result datatype */
5752
5753 /* Get back to outer memory context */
5754 MemoryContextSwitchTo(oldcontext);
5755
5756 /*
5757 * Must copy result out of sub-context used by expression eval.
5758 *
5759 * Also, if it's varlena, forcibly detoast it. This protects us against
5760 * storing TOAST pointers into plans that might outlive the referenced
5761 * data. (makeConst would handle detoasting anyway, but it's worth a few
5762 * extra lines here so that we can do the copy and detoast in one step.)
5763 */
5764 if (!const_is_null)
5765 {
5766 if (resultTypLen == -1)
5768 else
5770 }
5771
5772 /* Release all the junk we just created */
5773 FreeExecutorState(estate);
5774
5775 /*
5776 * Make the constant result node.
5777 */
5778 return (Expr *) makeConst(result_type, result_typmod, result_collation,
5782}
5783
5784
5785/*
5786 * inline_function_in_from
5787 * Attempt to "inline" a function in the FROM clause.
5788 *
5789 * "rte" is an RTE_FUNCTION rangetable entry. If it represents a call of a
5790 * function that can be inlined, expand the function and return the
5791 * substitute Query structure. Otherwise, return NULL.
5792 *
5793 * We assume that the RTE's expression has already been put through
5794 * eval_const_expressions(), which among other things will take care of
5795 * default arguments and named-argument notation.
5796 *
5797 * This has a good deal of similarity to inline_function(), but that's
5798 * for the general-expression case, and there are enough differences to
5799 * justify separate functions.
5800 */
5801Query *
5803{
5804 RangeTblFunction *rtfunc;
5805 FuncExpr *fexpr;
5806 Oid func_oid;
5811 Datum tmp;
5812 char *src;
5813 inline_error_callback_arg callback_arg;
5815 Query *querytree = NULL;
5816
5817 Assert(rte->rtekind == RTE_FUNCTION);
5818
5819 /*
5820 * Guard against infinite recursion during expansion by checking for stack
5821 * overflow. (There's no need to do more.)
5822 */
5824
5825 /* Fail if the RTE has ORDINALITY - we don't implement that here. */
5826 if (rte->funcordinality)
5827 return NULL;
5828
5829 /* Fail if RTE isn't a single, simple FuncExpr */
5830 if (list_length(rte->functions) != 1)
5831 return NULL;
5832 rtfunc = (RangeTblFunction *) linitial(rte->functions);
5833
5834 if (!IsA(rtfunc->funcexpr, FuncExpr))
5835 return NULL;
5836 fexpr = (FuncExpr *) rtfunc->funcexpr;
5837
5838 func_oid = fexpr->funcid;
5839
5840 /*
5841 * Refuse to inline if the arguments contain any volatile functions or
5842 * sub-selects. Volatile functions are rejected because inlining may
5843 * result in the arguments being evaluated multiple times, risking a
5844 * change in behavior. Sub-selects are rejected partly for implementation
5845 * reasons (pushing them down another level might change their behavior)
5846 * and partly because they're likely to be expensive and so multiple
5847 * evaluation would be bad.
5848 */
5849 if (contain_volatile_functions((Node *) fexpr->args) ||
5850 contain_subplans((Node *) fexpr->args))
5851 return NULL;
5852
5853 /* Check permission to call function (fail later, if not) */
5855 return NULL;
5856
5857 /* Check whether a plugin wants to hook function entry/exit */
5859 return NULL;
5860
5861 /*
5862 * OK, let's take a look at the function's pg_proc entry.
5863 */
5866 elog(ERROR, "cache lookup failed for function %u", func_oid);
5868
5869 /*
5870 * If the function SETs any configuration parameters, inlining would cause
5871 * us to miss making those changes.
5872 */
5874 {
5876 return NULL;
5877 }
5878
5879 /*
5880 * Make a temporary memory context, so that we don't leak all the stuff
5881 * that parsing and rewriting might create. If we succeed, we'll copy
5882 * just the finished query tree back up to the caller's context.
5883 */
5885 "inline_function_in_from",
5888
5889 /* Fetch the function body */
5891 src = TextDatumGetCString(tmp);
5892
5893 /*
5894 * If the function has an attached support function that can handle
5895 * SupportRequestInlineInFrom, then attempt to inline with that.
5896 */
5897 if (funcform->prosupport)
5898 {
5900
5902 req.root = root;
5903 req.rtfunc = rtfunc;
5904 req.proc = func_tuple;
5905
5906 querytree = (Query *)
5908 PointerGetDatum(&req)));
5909 }
5910
5911 /*
5912 * Setup error traceback support for ereport(). This is so that we can
5913 * finger the function that bad information came from. We don't install
5914 * this while running the support function, since it'd be likely to do the
5915 * wrong thing: any parse errors reported during that are very likely not
5916 * against the raw function source text.
5917 */
5918 callback_arg.proname = NameStr(funcform->proname);
5919 callback_arg.prosrc = src;
5920
5922 sqlerrcontext.arg = &callback_arg;
5925
5926 /*
5927 * If SupportRequestInlineInFrom didn't work, try our built-in inlining
5928 * mechanism.
5929 */
5930 if (!querytree)
5932 func_tuple, funcform, src);
5933
5934 if (!querytree)
5935 goto fail; /* no luck there either, fail */
5936
5937 /*
5938 * The result had better be a SELECT Query.
5939 */
5941 Assert(querytree->commandType == CMD_SELECT);
5942
5943 /*
5944 * Looks good --- substitute parameters into the query.
5945 */
5947 funcform->pronargs,
5948 fexpr->args);
5949
5950 /*
5951 * Copy the modified query out of the temporary memory context, and clean
5952 * up.
5953 */
5955
5957
5961
5962 /*
5963 * We don't have to fix collations here because the upper query is already
5964 * parsed, ie, the collations in the RTE are what count.
5965 */
5966
5967 /*
5968 * Since there is now no trace of the function in the plan tree, we must
5969 * explicitly record the plan's dependency on the function.
5970 */
5972
5973 /*
5974 * We must also notice if the inserted query adds a dependency on the
5975 * calling role due to RLS quals.
5976 */
5977 if (querytree->hasRowSecurity)
5978 root->glob->dependsOnRole = true;
5979
5980 return querytree;
5981
5982 /* Here if func is not inlinable: release temp memory and return NULL */
5983fail:
5988
5989 return NULL;
5990}
5991
5992/*
5993 * inline_sql_function_in_from
5994 *
5995 * This implements inline_function_in_from for SQL-language functions.
5996 * Returns NULL if the function couldn't be inlined.
5997 *
5998 * The division of labor between here and inline_function_in_from is based
5999 * on the rule that inline_function_in_from should make all checks that are
6000 * certain to be required in both this case and the support-function case.
6001 * Support functions might also want to make checks analogous to the ones
6002 * made here, but then again they might not, or they might just assume that
6003 * the function they are attached to can validly be inlined.
6004 */
6005static Query *
6007 RangeTblFunction *rtfunc,
6008 FuncExpr *fexpr,
6011 const char *src)
6012{
6013 Datum sqlbody;
6014 bool isNull;
6018 TupleDesc rettupdesc;
6019
6020 /*
6021 * The function must be declared to return a set, else inlining would
6022 * change the results if the contained SELECT didn't return exactly one
6023 * row.
6024 */
6025 if (!fexpr->funcretset)
6026 return NULL;
6027
6028 /*
6029 * Forget it if the function is not SQL-language or has other showstopper
6030 * properties. In particular it mustn't be declared STRICT, since we
6031 * couldn't enforce that. It also mustn't be VOLATILE, because that is
6032 * supposed to cause it to be executed with its own snapshot, rather than
6033 * sharing the snapshot of the calling query. We also disallow returning
6034 * SETOF VOID, because inlining would result in exposing the actual result
6035 * of the function's last SELECT, which should not happen in that case.
6036 * (Rechecking prokind, proretset, and pronargs is just paranoia.)
6037 */
6038 if (funcform->prolang != SQLlanguageId ||
6039 funcform->prokind != PROKIND_FUNCTION ||
6040 funcform->proisstrict ||
6041 funcform->provolatile == PROVOLATILE_VOLATILE ||
6042 funcform->prorettype == VOIDOID ||
6043 funcform->prosecdef ||
6044 !funcform->proretset ||
6045 list_length(fexpr->args) != funcform->pronargs)
6046 return NULL;
6047
6048 /* If we have prosqlbody, pay attention to that not prosrc */
6050 func_tuple,
6052 &isNull);
6053 if (!isNull)
6054 {
6055 Node *n;
6056
6058 if (IsA(n, List))
6060 else
6062 if (list_length(querytree_list) != 1)
6063 return NULL;
6065
6066 /* Acquire necessary locks, then apply rewriter. */
6067 AcquireRewriteLocks(querytree, true, false);
6069 if (list_length(querytree_list) != 1)
6070 return NULL;
6072 }
6073 else
6074 {
6077
6078 /*
6079 * Set up to handle parameters while parsing the function body. We
6080 * can use the FuncExpr just created as the input for
6081 * prepare_sql_fn_parse_info.
6082 */
6084 (Node *) fexpr,
6085 fexpr->inputcollid);
6086
6087 /*
6088 * Parse, analyze, and rewrite (unlike inline_function(), we can't
6089 * skip rewriting here). We can fail as soon as we find more than one
6090 * query, though.
6091 */
6094 return NULL;
6095
6097 src,
6099 pinfo, NULL);
6100 if (list_length(querytree_list) != 1)
6101 return NULL;
6103 }
6104
6105 /*
6106 * Also resolve the actual function result tupdesc, if composite. If we
6107 * have a coldeflist, believe that; otherwise use get_expr_result_type.
6108 * (This logic should match ExecInitFunctionScan.)
6109 */
6110 if (rtfunc->funccolnames != NIL)
6111 {
6113 rettupdesc = BuildDescFromLists(rtfunc->funccolnames,
6114 rtfunc->funccoltypes,
6115 rtfunc->funccoltypmods,
6116 rtfunc->funccolcollations);
6117 }
6118 else
6119 functypclass = get_expr_result_type((Node *) fexpr, NULL, &rettupdesc);
6120
6121 /*
6122 * The single command must be a plain SELECT.
6123 */
6124 if (!IsA(querytree, Query) ||
6125 querytree->commandType != CMD_SELECT)
6126 return NULL;
6127
6128 /*
6129 * Make sure the function (still) returns what it's declared to. This
6130 * will raise an error if wrong, but that's okay since the function would
6131 * fail at runtime anyway. Note that check_sql_fn_retval will also insert
6132 * coercions if needed to make the tlist expression(s) match the declared
6133 * type of the function. We also ask it to insert dummy NULL columns for
6134 * any dropped columns in rettupdesc, so that the elements of the modified
6135 * tlist match up to the attribute numbers.
6136 *
6137 * If the function returns a composite type, don't inline unless the check
6138 * shows it's returning a whole tuple result; otherwise what it's
6139 * returning is a single composite column which is not what we need.
6140 */
6142 fexpr->funcresulttype, rettupdesc,
6143 funcform->prokind,
6144 true) &&
6148 return NULL; /* reject not-whole-tuple-result cases */
6149
6150 /*
6151 * check_sql_fn_retval might've inserted a projection step, but that's
6152 * fine; just make sure we use the upper Query.
6153 */
6155
6156 return querytree;
6157}
6158
6159/*
6160 * Replace Param nodes by appropriate actual parameters
6161 *
6162 * This is just enough different from substitute_actual_parameters()
6163 * that it needs its own code.
6164 */
6165static Query *
6166substitute_actual_parameters_in_from(Query *expr, int nargs, List *args)
6167{
6169
6170 context.nargs = nargs;
6171 context.args = args;
6172 context.sublevels_up = 1;
6173
6174 return query_tree_mutator(expr,
6176 &context,
6177 0);
6178}
6179
6180static Node *
6183{
6184 Node *result;
6185
6186 if (node == NULL)
6187 return NULL;
6188 if (IsA(node, Query))
6189 {
6190 context->sublevels_up++;
6191 result = (Node *) query_tree_mutator((Query *) node,
6193 context,
6194 0);
6195 context->sublevels_up--;
6196 return result;
6197 }
6198 if (IsA(node, Param))
6199 {
6200 Param *param = (Param *) node;
6201
6202 if (param->paramkind == PARAM_EXTERN)
6203 {
6204 if (param->paramid <= 0 || param->paramid > context->nargs)
6205 elog(ERROR, "invalid paramid: %d", param->paramid);
6206
6207 /*
6208 * Since the parameter is being inserted into a subquery, we must
6209 * adjust levels.
6210 */
6211 result = copyObject(list_nth(context->args, param->paramid - 1));
6213 return result;
6214 }
6215 }
6216 return expression_tree_mutator(node,
6218 context);
6219}
6220
6221/*
6222 * pull_paramids
6223 * Returns a Bitmapset containing the paramids of all Params in 'expr'.
6224 */
6225Bitmapset *
6226pull_paramids(Expr *expr)
6227{
6229
6230 (void) pull_paramids_walker((Node *) expr, &result);
6231
6232 return result;
6233}
6234
6235static bool
6236pull_paramids_walker(Node *node, Bitmapset **context)
6237{
6238 if (node == NULL)
6239 return false;
6240 if (IsA(node, Param))
6241 {
6242 Param *param = (Param *) node;
6243
6244 *context = bms_add_member(*context, param->paramid);
6245 return false;
6246 }
6247 return expression_tree_walker(node, pull_paramids_walker, context);
6248}
6249
6250/*
6251 * Build ScalarArrayOpExpr on top of 'exprs.' 'haveNonConst' indicates
6252 * whether at least one of the expressions is not Const. When it's false,
6253 * the array constant is built directly; otherwise, we have to build a child
6254 * ArrayExpr. The 'exprs' list gets freed if not directly used in the output
6255 * expression tree.
6256 */
6259 Oid inputcollid, List *exprs, bool haveNonConst)
6260{
6261 Node *arrayNode = NULL;
6263 Oid arraytype = get_array_type(coltype);
6264
6265 if (!OidIsValid(arraytype))
6266 return NULL;
6267
6268 /*
6269 * Assemble an array from the list of constants. It seems more profitable
6270 * to build a const array. But in the presence of other nodes, we don't
6271 * have a specific value here and must employ an ArrayExpr instead.
6272 */
6273 if (haveNonConst)
6274 {
6276
6277 /* array_collid will be set by parse_collate.c */
6278 arrayExpr->element_typeid = coltype;
6279 arrayExpr->array_typeid = arraytype;
6280 arrayExpr->multidims = false;
6281 arrayExpr->elements = exprs;
6282 arrayExpr->location = -1;
6283
6284 arrayNode = (Node *) arrayExpr;
6285 }
6286 else
6287 {
6288 int16 typlen;
6289 bool typbyval;
6290 char typalign;
6291 Datum *elems;
6292 bool *nulls;
6293 int i = 0;
6295 int dims[1] = {list_length(exprs)};
6296 int lbs[1] = {1};
6297
6298 get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign);
6299
6300 elems = palloc_array(Datum, list_length(exprs));
6301 nulls = palloc_array(bool, list_length(exprs));
6302 foreach_node(Const, value, exprs)
6303 {
6304 elems[i] = value->constvalue;
6305 nulls[i++] = value->constisnull;
6306 }
6307
6308 arrayConst = construct_md_array(elems, nulls, 1, dims, lbs,
6309 coltype, typlen, typbyval, typalign);
6312 false, false);
6313
6314 pfree(elems);
6315 pfree(nulls);
6316 list_free(exprs);
6317 }
6318
6319 /* Build the SAOP expression node */
6321 saopexpr->opno = oper;
6322 saopexpr->opfuncid = get_opcode(oper);
6323 saopexpr->hashfuncid = InvalidOid;
6324 saopexpr->negfuncid = InvalidOid;
6325 saopexpr->useOr = true;
6326 saopexpr->inputcollid = inputcollid;
6328 saopexpr->location = -1;
6329
6330 return saopexpr;
6331}
Datum querytree(PG_FUNCTION_ARGS)
Definition _int_bool.c:665
@ ACLCHECK_OK
Definition acl.h:184
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3879
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_DATA_PTR(a)
Definition array.h:322
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_DIMS(a)
Definition array.h:294
#define ARR_HASNULL(a)
Definition array.h:291
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
#define InvalidAttrNumber
Definition attnum.h:23
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
#define bms_is_empty(a)
Definition bitmapset.h:118
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:835
#define Assert(condition)
Definition c.h:943
int16_t int16
Definition c.h:619
int32_t int32
Definition c.h:620
#define OidIsValid(objectId)
Definition c.h:858
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
static List * simplify_or_arguments(List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceTrue)
Definition clauses.c:4211
static bool rowtype_field_matches(Oid rowtypeid, int fieldnum, Oid expectedtype, int32 expectedtypmod, Oid expectedcollation)
Definition clauses.c:2431
Query * inline_function_in_from(PlannerInfo *root, RangeTblEntry *rte)
Definition clauses.c:5803
static List * add_function_defaults(List *args, int pronargs, HeapTuple func_tuple)
Definition clauses.c:5065
#define ece_all_arguments_const(node)
Definition clauses.c:2672
#define ece_evaluate_expr(node)
Definition clauses.c:2676
bool contain_mutable_functions(Node *clause)
Definition clauses.c:383
#define ece_generic_processing(node)
Definition clauses.c:2663
static Expr * evaluate_function(Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, List *args, bool funcvariadic, HeapTuple func_tuple, eval_const_expressions_context *context)
Definition clauses.c:5164
static Node * substitute_actual_parameters_mutator(Node *node, substitute_actual_parameters_context *context)
Definition clauses.c:5659
static bool ece_function_is_safe(Oid funcid, eval_const_expressions_context *context)
Definition clauses.c:4173
static List * simplify_and_arguments(List *args, eval_const_expressions_context *context, bool *haveNull, bool *forceFalse)
Definition clauses.c:4317
static Expr * simplify_function(Oid funcid, Oid result_type, int32 result_typmod, Oid result_collid, Oid input_collid, List **args_p, bool funcvariadic, bool process_args, bool allow_non_const, eval_const_expressions_context *context)
Definition clauses.c:4480
static Expr * inline_function(Oid funcid, Oid result_type, Oid result_collid, Oid input_collid, List *args, bool funcvariadic, HeapTuple func_tuple, eval_const_expressions_context *context)
Definition clauses.c:5290
static List * reorder_function_arguments(List *args, int pronargs, HeapTuple func_tuple)
Definition clauses.c:4995
static Node * simplify_aggref(Aggref *aggref, eval_const_expressions_context *context)
Definition clauses.c:4586
static Node * substitute_actual_parameters(Node *expr, int nargs, List *args, int *usecounts)
Definition clauses.c:5646
static Query * substitute_actual_parameters_in_from(Query *expr, int nargs, List *args)
Definition clauses.c:6167
bool expr_is_nonnullable(PlannerInfo *root, Expr *expr, NotNullSource source)
Definition clauses.c:4772
static void sql_inline_error_callback(void *arg)
Definition clauses.c:5687
static bool contain_non_const_walker(Node *node, void *context)
Definition clauses.c:4157
static bool contain_context_dependent_node(Node *clause)
Definition clauses.c:1194
static void recheck_cast_function_args(List *args, Oid result_type, Oid *proargtypes, int pronargs, HeapTuple func_tuple)
Definition clauses.c:5119
List * expand_function_arguments(List *args, bool include_out_arguments, Oid result_type, HeapTuple func_tuple)
Definition clauses.c:4914
bool contain_nonstrict_functions(Node *clause)
Definition clauses.c:1006
static Node * substitute_actual_parameters_in_from_mutator(Node *node, substitute_actual_parameters_in_from_context *context)
Definition clauses.c:6182
static Query * inline_sql_function_in_from(PlannerInfo *root, RangeTblFunction *rtfunc, FuncExpr *fexpr, HeapTuple func_tuple, Form_pg_proc funcform, const char *src)
Definition clauses.c:6007
bool contain_subplans(Node *clause)
Definition clauses.c:343
static Node * simplify_boolean_equality(Oid opno, List *args)
Definition clauses.c:4411
Bitmapset * pull_paramids(Expr *expr)
Definition clauses.c:6227
ScalarArrayOpExpr * make_SAOP_expr(Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid, Oid inputcollid, List *exprs, bool haveNonConst)
Definition clauses.c:6259
bool var_is_nonnullable(PlannerInfo *root, Var *var, NotNullSource source)
Definition clauses.c:4628
static Node * eval_const_expressions_mutator(Node *node, eval_const_expressions_context *context)
Definition clauses.c:2686
static bool pull_paramids_walker(Node *node, Bitmapset **context)
Definition clauses.c:6237
Expr * evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation)
Definition clauses.c:5711
static List * fetch_function_defaults(HeapTuple func_tuple)
Definition clauses.c:5089
bool contain_volatile_functions(Node *clause)
Definition clauses.c:551
double cpu_operator_cost
Definition costsize.c:135
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition costsize.c:4900
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
Datum arg
Definition elog.c:1323
ErrorContextCallback * error_context_stack
Definition elog.c:100
#define errcontext
Definition elog.h:200
int internalerrquery(const char *query)
int internalerrposition(int cursorpos)
#define ERROR
Definition elog.h:40
int geterrposition(void)
#define elog(elevel,...)
Definition elog.h:228
int errposition(int cursorpos)
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition execExpr.c:143
void FreeExecutorState(EState *estate)
Definition execUtils.c:197
EState * CreateExecutorState(void)
Definition execUtils.c:90
#define GetPerTupleExprContext(estate)
Definition executor.h:667
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:446
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define OidFunctionCall1(functionId, arg1)
Definition fmgr.h:722
#define PG_DETOAST_DATUM_COPY(datum)
Definition fmgr.h:242
#define FmgrHookIsNeeded(fn_oid)
Definition fmgr.h:850
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:299
TypeFuncClass
Definition funcapi.h:147
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
@ TYPEFUNC_RECORD
Definition funcapi.h:151
@ TYPEFUNC_COMPOSITE_DOMAIN
Definition funcapi.h:150
bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)
Definition functions.c:2117
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition functions.c:341
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
Definition functions.c:252
const char * str
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
static struct @177 value
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_delete_first(List *list)
Definition list.c:943
List * list_concat_copy(const List *list1, const List *list2)
Definition list.c:598
List * list_copy(const List *oldlist)
Definition list.c:1573
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
List * list_delete_last(List *list)
Definition list.c:957
void list_free(List *list)
Definition list.c:1546
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722
List * list_delete_first_n(List *list, int n)
Definition list.c:983
#define NoLock
Definition lockdefs.h:34
RegProcedure get_func_support(Oid funcid)
Definition lsyscache.c:2051
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3102
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2464
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition lsyscache.c:2444
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1478
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3069
char func_volatile(Oid funcid)
Definition lsyscache.c:1973
Oid get_array_type(Oid typid)
Definition lsyscache.c:2982
Expr * make_orclause(List *orclauses)
Definition makefuncs.c:743
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition makefuncs.c:66
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition makefuncs.c:388
Node * makeBoolConst(bool value, bool isnull)
Definition makefuncs.c:408
Expr * make_andclause(List *andclauses)
Definition makefuncs.c:727
Expr * make_notclause(Expr *notclause)
Definition makefuncs.c:759
JsonValueExpr * makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr, JsonFormat *format)
Definition makefuncs.c:938
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition makefuncs.c:350
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc0(Size size)
Definition mcxt.c:1417
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
Oid GetUserId(void)
Definition miscinit.c:470
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
Node * applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat, int rlocation, bool overwrite_ok)
Definition nodeFuncs.c:641
void fix_opfuncids(Node *node)
Definition nodeFuncs.c:1848
void set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
Definition nodeFuncs.c:1890
void set_opfuncid(OpExpr *opexpr)
Definition nodeFuncs.c:1879
#define expression_tree_mutator(n, m, c)
Definition nodeFuncs.h:155
static bool is_andclause(const void *clause)
Definition nodeFuncs.h:107
static bool is_orclause(const void *clause)
Definition nodeFuncs.h:116
#define expression_tree_walker(n, w, c)
Definition nodeFuncs.h:153
#define query_tree_mutator(q, m, c, f)
Definition nodeFuncs.h:160
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define copyObject(obj)
Definition nodes.h:232
#define nodeTag(nodeptr)
Definition nodes.h:139
@ CMD_SELECT
Definition nodes.h:275
#define makeNode(_type_)
Definition nodes.h:161
#define castNode(_type_, nodeptr)
Definition nodes.h:182
NotNullSource
Definition optimizer.h:135
@ NOTNULL_SOURCE_HASHTABLE
Definition optimizer.h:137
@ NOTNULL_SOURCE_RELOPT
Definition optimizer.h:136
@ NOTNULL_SOURCE_CATALOG
Definition optimizer.h:138
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
#define PARAM_FLAG_CONST
Definition params.h:87
void(* ParserSetupHook)(ParseState *pstate, void *arg)
Definition params.h:107
Oid enforce_generic_type_consistency(const Oid *actual_arg_types, Oid *declared_arg_types, int nargs, Oid rettype, bool allow_poly)
void make_fn_arguments(ParseState *pstate, List *fargs, Oid *actual_arg_types, Oid *declared_arg_types)
void free_parsestate(ParseState *pstate)
Definition parse_node.c:72
ParseState * make_parsestate(ParseState *parentParseState)
Definition parse_node.c:39
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition parse_oper.c:373
@ RTE_FUNCTION
@ RTE_RELATION
#define ACL_EXECUTE
Definition parsenodes.h:83
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition analyze.c:271
#define planner_rt_fetch(rti, root)
Definition pathnodes.h:704
#define FUNC_MAX_ARGS
bool has_subclass(Oid relationId)
#define lfirst(lc)
Definition pg_list.h:172
#define lfirst_node(type, lc)
Definition pg_list.h:176
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial_node(type, l)
Definition pg_list.h:181
#define NIL
Definition pg_list.h:68
#define list_make1(x1)
Definition pg_list.h:244
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
#define linitial(l)
Definition pg_list.h:178
#define list_make3(x1, x2, x3)
Definition pg_list.h:248
#define lsecond(l)
Definition pg_list.h:183
#define foreach_node(type, var, lst)
Definition pg_list.h:528
#define list_make2(x1, x2)
Definition pg_list.h:246
int16 pronargs
Definition pg_proc.h:83
END_CATALOG_STRUCT typedef FormData_pg_proc * Form_pg_proc
Definition pg_proc.h:140
static rewind_source * source
Definition pg_rewind.c:89
char typalign
Definition pg_type.h:178
Bitmapset * find_relation_notnullatts(PlannerInfo *root, Oid relid)
Definition plancat.c:763
List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition postgres.c:774
List * pg_parse_query(const char *query_string)
Definition postgres.c:615
List * pg_rewrite_query(Query *query)
Definition postgres.c:814
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define PointerGetDatum(X)
Definition postgres.h:354
#define InvalidOid
unsigned int Oid
Node * negate_clause(Node *node)
Definition prepqual.c:73
e
static int fb(int x)
@ IS_NOT_TRUE
Definition primnodes.h:2004
@ IS_NOT_FALSE
Definition primnodes.h:2004
@ IS_NOT_UNKNOWN
Definition primnodes.h:2004
@ IS_TRUE
Definition primnodes.h:2004
@ IS_UNKNOWN
Definition primnodes.h:2004
@ IS_FALSE
Definition primnodes.h:2004
@ AND_EXPR
Definition primnodes.h:964
@ OR_EXPR
Definition primnodes.h:964
@ NOT_EXPR
Definition primnodes.h:964
@ PARAM_EXTERN
Definition primnodes.h:385
@ VAR_RETURNING_DEFAULT
Definition primnodes.h:257
@ COERCE_IMPLICIT_CAST
Definition primnodes.h:769
@ COERCE_EXPLICIT_CALL
Definition primnodes.h:767
@ IS_NULL
Definition primnodes.h:1980
@ IS_NOT_NULL
Definition primnodes.h:1980
tree ctl root
Definition radixtree.h:1857
void * stringToNode(const char *str)
Definition read.c:90
#define RelationGetDescr(relation)
Definition rel.h:542
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition relnode.c:544
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
void record_plan_type_dependency(PlannerInfo *root, Oid typid)
Definition setrefs.c:3672
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition setrefs.c:3632
void check_stack_depth(void)
Definition stack_depth.c:95
Oid aggfnoid
Definition primnodes.h:464
BoolExprType boolop
Definition primnodes.h:972
List * args
Definition primnodes.h:973
ParseLoc location
Definition primnodes.h:1249
ParseLoc location
Definition primnodes.h:1316
char attnullability
Definition tupdesc.h:80
Oid consttype
Definition primnodes.h:330
MemoryContext es_query_cxt
Definition execnodes.h:746
struct ErrorContextCallback * previous
Definition elog.h:299
Expr xpr
Definition primnodes.h:781
ParseLoc location
Definition primnodes.h:803
Oid funcid
Definition primnodes.h:783
List * args
Definition primnodes.h:801
Definition pg_list.h:54
Definition nodes.h:135
NodeTag type
Definition nodes.h:136
Oid opno
Definition primnodes.h:851
List * args
Definition primnodes.h:869
ParseLoc location
Definition primnodes.h:872
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition params.h:124
ParamFetchHook paramFetch
Definition params.h:111
ParseLoc location
Definition primnodes.h:404
int32 paramtypmod
Definition primnodes.h:400
int paramid
Definition primnodes.h:397
Oid paramtype
Definition primnodes.h:398
ParamKind paramkind
Definition primnodes.h:396
Oid paramcollid
Definition primnodes.h:402
const char * p_sourcetext
Definition parse_node.h:214
Bitmapset * notnullattnums
Definition pathnodes.h:1083
List * args
Definition primnodes.h:1450
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270
VarReturningType varreturningtype
Definition primnodes.h:298
Index varlevelsup
Definition primnodes.h:295
List * args
Definition primnodes.h:606
Index winref
Definition primnodes.h:612
Expr * aggfilter
Definition primnodes.h:608
ParseLoc location
Definition primnodes.h:620
int ignore_nulls
Definition primnodes.h:618
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:626
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations)
Definition tupdesc.c:1109
#define ATTNULLABLE_VALID
Definition tupdesc.h:86
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:195
bool DomainHasConstraints(Oid type_id, bool *has_volatile)
Definition typcache.c:1495

◆ ece_evaluate_expr

#define ece_evaluate_expr (   node)
Value:
((Node *) evaluate_expr((Expr *) (node), \
exprType((Node *) (node)), \
exprTypmod((Node *) (node)), \
exprCollation((Node *) (node))))

Definition at line 2676 of file clauses.c.

◆ ece_generic_processing

#define ece_generic_processing (   node)
Value:

Definition at line 2663 of file clauses.c.

◆ MIN_ARRAY_SIZE_FOR_HASHED_SAOP

#define MIN_ARRAY_SIZE_FOR_HASHED_SAOP   9

Definition at line 2515 of file clauses.c.

Function Documentation

◆ add_function_defaults()

static List * add_function_defaults ( List args,
int  pronargs,
HeapTuple  func_tuple 
)
static

Definition at line 5065 of file clauses.c.

5066{
5067 int nargsprovided = list_length(args);
5068 List *defaults;
5069 int ndelete;
5070
5071 /* Get all the default expressions from the pg_proc tuple */
5073
5074 /* Delete any unused defaults from the list */
5075 ndelete = nargsprovided + list_length(defaults) - pronargs;
5076 if (ndelete < 0)
5077 elog(ERROR, "not enough default arguments");
5078 if (ndelete > 0)
5079 defaults = list_delete_first_n(defaults, ndelete);
5080
5081 /* And form the combined argument list, not modifying the input list */
5082 return list_concat_copy(args, defaults);
5083}

References elog, ERROR, fb(), fetch_function_defaults(), list_concat_copy(), list_delete_first_n(), list_length(), and pronargs.

Referenced by expand_function_arguments().

◆ CommuteOpExpr()

void CommuteOpExpr ( OpExpr clause)

Definition at line 2392 of file clauses.c.

2393{
2394 Oid opoid;
2395 Node *temp;
2396
2397 /* Sanity checks: caller is at fault if these fail */
2398 if (!is_opclause(clause) ||
2399 list_length(clause->args) != 2)
2400 elog(ERROR, "cannot commute non-binary-operator clause");
2401
2402 opoid = get_commutator(clause->opno);
2403
2404 if (!OidIsValid(opoid))
2405 elog(ERROR, "could not find commutator for operator %u",
2406 clause->opno);
2407
2408 /*
2409 * modify the clause in-place!
2410 */
2411 clause->opno = opoid;
2412 clause->opfuncid = InvalidOid;
2413 /* opresulttype, opretset, opcollid, inputcollid need not change */
2414
2415 temp = linitial(clause->args);
2416 linitial(clause->args) = lsecond(clause->args);
2417 lsecond(clause->args) = temp;
2418}
Oid get_commutator(Oid opno)
Definition lsyscache.c:1702
static bool is_opclause(const void *clause)
Definition nodeFuncs.h:76

References OpExpr::args, elog, ERROR, fb(), get_commutator(), InvalidOid, is_opclause(), linitial, list_length(), lsecond, OidIsValid, and OpExpr::opno.

Referenced by get_switched_clauses().

◆ contain_agg_clause()

bool contain_agg_clause ( Node clause)

Definition at line 194 of file clauses.c.

195{
196 return contain_agg_clause_walker(clause, NULL);
197}
static bool contain_agg_clause_walker(Node *node, void *context)
Definition clauses.c:200

References contain_agg_clause_walker(), and fb().

Referenced by get_eclass_for_sort_expr(), mark_nullable_by_grouping(), and subquery_planner().

◆ contain_agg_clause_walker()

static bool contain_agg_clause_walker ( Node node,
void context 
)
static

Definition at line 200 of file clauses.c.

201{
202 if (node == NULL)
203 return false;
204 if (IsA(node, Aggref))
205 {
206 Assert(((Aggref *) node)->agglevelsup == 0);
207 return true; /* abort the tree traversal and return true */
208 }
209 if (IsA(node, GroupingFunc))
210 {
211 Assert(((GroupingFunc *) node)->agglevelsup == 0);
212 return true; /* abort the tree traversal and return true */
213 }
214 Assert(!IsA(node, SubLink));
216}

References Assert, contain_agg_clause_walker(), expression_tree_walker, fb(), and IsA.

Referenced by contain_agg_clause(), and contain_agg_clause_walker().

◆ contain_context_dependent_node()

static bool contain_context_dependent_node ( Node clause)
static

Definition at line 1194 of file clauses.c.

1195{
1196 int flags = 0;
1197
1198 return contain_context_dependent_node_walker(clause, &flags);
1199}
static bool contain_context_dependent_node_walker(Node *node, int *flags)
Definition clauses.c:1204

References contain_context_dependent_node_walker().

Referenced by inline_function().

◆ contain_context_dependent_node_walker()

static bool contain_context_dependent_node_walker ( Node node,
int flags 
)
static

Definition at line 1204 of file clauses.c.

1205{
1206 if (node == NULL)
1207 return false;
1208 if (IsA(node, CaseTestExpr))
1209 return !(*flags & CCDN_CASETESTEXPR_OK);
1210 else if (IsA(node, CaseExpr))
1211 {
1212 CaseExpr *caseexpr = (CaseExpr *) node;
1213
1214 /*
1215 * If this CASE doesn't have a test expression, then it doesn't create
1216 * a context in which CaseTestExprs should appear, so just fall
1217 * through and treat it as a generic expression node.
1218 */
1219 if (caseexpr->arg)
1220 {
1221 int save_flags = *flags;
1222 bool res;
1223
1224 /*
1225 * Note: in principle, we could distinguish the various sub-parts
1226 * of a CASE construct and set the flag bit only for some of them,
1227 * since we are only expecting CaseTestExprs to appear in the
1228 * "expr" subtree of the CaseWhen nodes. But it doesn't really
1229 * seem worth any extra code. If there are any bare CaseTestExprs
1230 * elsewhere in the CASE, something's wrong already.
1231 */
1232 *flags |= CCDN_CASETESTEXPR_OK;
1233 res = expression_tree_walker(node,
1235 flags);
1236 *flags = save_flags;
1237 return res;
1238 }
1239 }
1240 else if (IsA(node, ArrayCoerceExpr))
1241 {
1243 int save_flags;
1244 bool res;
1245
1246 /* Check the array expression */
1247 if (contain_context_dependent_node_walker((Node *) ac->arg, flags))
1248 return true;
1249
1250 /* Check the elemexpr, which is allowed to contain CaseTestExpr */
1251 save_flags = *flags;
1252 *flags |= CCDN_CASETESTEXPR_OK;
1253 res = contain_context_dependent_node_walker((Node *) ac->elemexpr,
1254 flags);
1255 *flags = save_flags;
1256 return res;
1257 }
1259 flags);
1260}
#define CCDN_CASETESTEXPR_OK
Definition clauses.c:1201

References CCDN_CASETESTEXPR_OK, contain_context_dependent_node_walker(), expression_tree_walker, fb(), and IsA.

Referenced by contain_context_dependent_node(), and contain_context_dependent_node_walker().

◆ contain_exec_param()

bool contain_exec_param ( Node clause,
List param_ids 
)

Definition at line 1152 of file clauses.c.

1153{
1154 return contain_exec_param_walker(clause, param_ids);
1155}
static bool contain_exec_param_walker(Node *node, List *param_ids)
Definition clauses.c:1158

References contain_exec_param_walker(), and fb().

Referenced by test_opexpr_is_hashable().

◆ contain_exec_param_walker()

static bool contain_exec_param_walker ( Node node,
List param_ids 
)
static

Definition at line 1158 of file clauses.c.

1159{
1160 if (node == NULL)
1161 return false;
1162 if (IsA(node, Param))
1163 {
1164 Param *p = (Param *) node;
1165
1166 if (p->paramkind == PARAM_EXEC &&
1168 return true;
1169 }
1171}
bool list_member_int(const List *list, int datum)
Definition list.c:702
@ PARAM_EXEC
Definition primnodes.h:386

References contain_exec_param_walker(), expression_tree_walker, fb(), IsA, list_member_int(), PARAM_EXEC, Param::paramid, and Param::paramkind.

Referenced by contain_exec_param(), and contain_exec_param_walker().

◆ contain_leaked_vars()

bool contain_leaked_vars ( Node clause)

Definition at line 1278 of file clauses.c.

1279{
1280 return contain_leaked_vars_walker(clause, NULL);
1281}
static bool contain_leaked_vars_walker(Node *node, void *context)
Definition clauses.c:1290

References contain_leaked_vars_walker(), and fb().

Referenced by make_plain_restrictinfo(), and qual_is_pushdown_safe().

◆ contain_leaked_vars_checker()

static bool contain_leaked_vars_checker ( Oid  func_id,
void context 
)
static

Definition at line 1284 of file clauses.c.

1285{
1286 return !get_func_leakproof(func_id);
1287}
bool get_func_leakproof(Oid funcid)
Definition lsyscache.c:2030

References fb(), and get_func_leakproof().

Referenced by contain_leaked_vars_walker().

◆ contain_leaked_vars_walker()

static bool contain_leaked_vars_walker ( Node node,
void context 
)
static

Definition at line 1290 of file clauses.c.

1291{
1292 if (node == NULL)
1293 return false;
1294
1295 switch (nodeTag(node))
1296 {
1297 case T_Var:
1298 case T_Const:
1299 case T_Param:
1300 case T_ArrayExpr:
1301 case T_FieldSelect:
1302 case T_FieldStore:
1303 case T_NamedArgExpr:
1304 case T_BoolExpr:
1305 case T_RelabelType:
1306 case T_CollateExpr:
1307 case T_CaseExpr:
1308 case T_CaseTestExpr:
1309 case T_RowExpr:
1310 case T_SQLValueFunction:
1311 case T_NullTest:
1312 case T_BooleanTest:
1313 case T_NextValueExpr:
1314 case T_ReturningExpr:
1315 case T_List:
1316
1317 /*
1318 * We know these node types don't contain function calls; but
1319 * something further down in the node tree might.
1320 */
1321 break;
1322
1323 case T_FuncExpr:
1324 case T_OpExpr:
1325 case T_DistinctExpr:
1326 case T_NullIfExpr:
1328 case T_CoerceViaIO:
1329 case T_ArrayCoerceExpr:
1330
1331 /*
1332 * If node contains a leaky function call, and there's any Var
1333 * underneath it, reject.
1334 */
1336 context) &&
1337 contain_var_clause(node))
1338 return true;
1339 break;
1340
1341 case T_SubscriptingRef:
1342 {
1343 SubscriptingRef *sbsref = (SubscriptingRef *) node;
1345
1346 /* Consult the subscripting support method info */
1347 sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype,
1348 NULL);
1349 if (!sbsroutines ||
1350 !(sbsref->refassgnexpr != NULL ?
1351 sbsroutines->store_leakproof :
1352 sbsroutines->fetch_leakproof))
1353 {
1354 /* Node is leaky, so reject if it contains Vars */
1355 if (contain_var_clause(node))
1356 return true;
1357 }
1358 }
1359 break;
1360
1361 case T_RowCompareExpr:
1362 {
1363 /*
1364 * It's worth special-casing this because a leaky comparison
1365 * function only compromises one pair of row elements, which
1366 * might not contain Vars while others do.
1367 */
1369 ListCell *opid;
1370 ListCell *larg;
1371 ListCell *rarg;
1372
1373 forthree(opid, rcexpr->opnos,
1374 larg, rcexpr->largs,
1375 rarg, rcexpr->rargs)
1376 {
1377 Oid funcid = get_opcode(lfirst_oid(opid));
1378
1379 if (!get_func_leakproof(funcid) &&
1380 (contain_var_clause((Node *) lfirst(larg)) ||
1381 contain_var_clause((Node *) lfirst(rarg))))
1382 return true;
1383 }
1384 }
1385 break;
1386
1387 case T_MinMaxExpr:
1388 {
1389 /*
1390 * MinMaxExpr is leakproof if the comparison function it calls
1391 * is leakproof.
1392 */
1393 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1394 TypeCacheEntry *typentry;
1395 bool leakproof;
1396
1397 /* Look up the btree comparison function for the datatype */
1398 typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1400 if (OidIsValid(typentry->cmp_proc))
1402 else
1403 {
1404 /*
1405 * The executor will throw an error, but here we just
1406 * treat the missing function as leaky.
1407 */
1408 leakproof = false;
1409 }
1410
1411 if (!leakproof &&
1413 return true;
1414 }
1415 break;
1416
1417 case T_CurrentOfExpr:
1418
1419 /*
1420 * WHERE CURRENT OF doesn't contain leaky function calls.
1421 * Moreover, it is essential that this is considered non-leaky,
1422 * since the planner must always generate a TID scan when CURRENT
1423 * OF is present -- cf. cost_tidscan.
1424 */
1425 return false;
1426
1427 default:
1428
1429 /*
1430 * If we don't recognize the node tag, assume it might be leaky.
1431 * This prevents an unexpected security hole if someone adds a new
1432 * node type that can call a function.
1433 */
1434 return true;
1435 }
1437 context);
1438}
static bool contain_leaked_vars_checker(Oid func_id, void *context)
Definition clauses.c:1284
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition lsyscache.c:3325
bool check_functions_in_node(Node *node, check_function_callback checker, void *context)
Definition nodeFuncs.c:1917
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition pg_list.h:595
#define lfirst_oid(lc)
Definition pg_list.h:174
Expr * refassgnexpr
Definition primnodes.h:736
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_CMP_PROC
Definition typcache.h:141
bool contain_var_clause(Node *node)
Definition var.c:406

References check_functions_in_node(), TypeCacheEntry::cmp_proc, contain_leaked_vars_checker(), contain_leaked_vars_walker(), contain_var_clause(), expression_tree_walker, fb(), forthree, get_func_leakproof(), get_opcode(), getSubscriptingRoutines(), lfirst, lfirst_oid, lookup_type_cache(), nodeTag, OidIsValid, SubscriptingRef::refassgnexpr, and TYPECACHE_CMP_PROC.

Referenced by contain_leaked_vars(), and contain_leaked_vars_walker().

◆ contain_mutable_functions()

◆ contain_mutable_functions_after_planning()

bool contain_mutable_functions_after_planning ( Expr expr)

Definition at line 503 of file clauses.c.

504{
505 /* We assume here that expression_planner() won't scribble on its input */
506 expr = expression_planner(expr);
507
508 /* Now we can search for non-immutable functions */
509 return contain_mutable_functions((Node *) expr);
510}
Expr * expression_planner(Expr *expr)
Definition planner.c:6839

References contain_mutable_functions(), and expression_planner().

Referenced by CheckPredicate(), ComputeIndexAttrs(), and cookDefault().

◆ contain_mutable_functions_checker()

static bool contain_mutable_functions_checker ( Oid  func_id,
void context 
)
static

Definition at line 389 of file clauses.c.

390{
392}

References fb(), and func_volatile().

Referenced by contain_mutable_functions_walker().

◆ contain_mutable_functions_walker()

static bool contain_mutable_functions_walker ( Node node,
void context 
)
static

Definition at line 395 of file clauses.c.

396{
397 if (node == NULL)
398 return false;
399 /* Check for mutable functions in node itself */
401 context))
402 return true;
403
404 if (IsA(node, JsonConstructorExpr))
405 {
407 ListCell *lc;
408 bool is_jsonb;
409
410 is_jsonb = ctor->returning->format->format_type == JS_FORMAT_JSONB;
411
412 /*
413 * Check argument_type => json[b] conversions specifically. We still
414 * recurse to check 'args' below, but here we want to specifically
415 * check whether or not the emitted clause would fail to be immutable
416 * because of TimeZone, for example.
417 */
418 foreach(lc, ctor->args)
419 {
420 Oid typid = exprType(lfirst(lc));
421
422 if (is_jsonb ?
423 !to_jsonb_is_immutable(typid) :
424 !to_json_is_immutable(typid))
425 return true;
426 }
427
428 /* Check all subnodes */
429 }
430
431 if (IsA(node, JsonExpr))
432 {
434 Const *cnst;
435
436 if (!IsA(jexpr->path_spec, Const))
437 return true;
438
439 cnst = castNode(Const, jexpr->path_spec);
440
441 Assert(cnst->consttype == JSONPATHOID);
442 if (cnst->constisnull)
443 return false;
444
445 if (jspIsMutable(DatumGetJsonPathP(cnst->constvalue),
446 jexpr->passing_names, jexpr->passing_values))
447 return true;
448 }
449
450 if (IsA(node, SQLValueFunction))
451 {
452 /* all variants of SQLValueFunction are stable */
453 return true;
454 }
455
456 if (IsA(node, NextValueExpr))
457 {
458 /* NextValueExpr is volatile */
459 return true;
460 }
461
462 /*
463 * It should be safe to treat MinMaxExpr as immutable, because it will
464 * depend on a non-cross-type btree comparison function, and those should
465 * always be immutable. Treating XmlExpr as immutable is more dubious,
466 * and treating CoerceToDomain as immutable is outright dangerous. But we
467 * have done so historically, and changing this would probably cause more
468 * problems than it would fix. In practice, if you have a non-immutable
469 * domain constraint you are in for pain anyhow.
470 */
471
472 /* Recurse to check arguments */
473 if (IsA(node, Query))
474 {
475 /* Recurse into subselects */
476 return query_tree_walker((Query *) node,
478 context, 0);
479 }
481 context);
482}
static bool contain_mutable_functions_checker(Oid func_id, void *context)
Definition clauses.c:389
return true
Definition isn.c:130
bool to_json_is_immutable(Oid typoid)
Definition json.c:696
bool to_jsonb_is_immutable(Oid typoid)
Definition jsonb.c:1081
bool jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
Definition jsonpath.c:1381
static JsonPath * DatumGetJsonPathP(Datum d)
Definition jsonpath.h:35
#define query_tree_walker(q, w, c, f)
Definition nodeFuncs.h:158
@ JS_FORMAT_JSONB
Definition primnodes.h:1667

References Assert, castNode, check_functions_in_node(), contain_mutable_functions_checker(), contain_mutable_functions_walker(), DatumGetJsonPathP(), expression_tree_walker, exprType(), fb(), IsA, JS_FORMAT_JSONB, jspIsMutable(), lfirst, query_tree_walker, to_json_is_immutable(), and to_jsonb_is_immutable().

Referenced by contain_mutable_functions(), and contain_mutable_functions_walker().

◆ contain_non_const_walker()

static bool contain_non_const_walker ( Node node,
void context 
)
static

Definition at line 4157 of file clauses.c.

4158{
4159 if (node == NULL)
4160 return false;
4161 if (IsA(node, Const))
4162 return false;
4163 if (IsA(node, List))
4164 return expression_tree_walker(node, contain_non_const_walker, context);
4165 /* Otherwise, abort the tree traversal and return true */
4166 return true;
4167}

References contain_non_const_walker(), expression_tree_walker, fb(), and IsA.

Referenced by contain_non_const_walker().

◆ contain_nonstrict_functions()

bool contain_nonstrict_functions ( Node clause)

Definition at line 1006 of file clauses.c.

1007{
1009}
static bool contain_nonstrict_functions_walker(Node *node, void *context)
Definition clauses.c:1018

References contain_nonstrict_functions_walker(), and fb().

Referenced by inline_function(), and pullup_replace_vars_callback().

◆ contain_nonstrict_functions_checker()

static bool contain_nonstrict_functions_checker ( Oid  func_id,
void context 
)
static

Definition at line 1012 of file clauses.c.

1013{
1014 return !func_strict(func_id);
1015}
bool func_strict(Oid funcid)
Definition lsyscache.c:1954

References fb(), and func_strict().

Referenced by contain_nonstrict_functions_walker().

◆ contain_nonstrict_functions_walker()

static bool contain_nonstrict_functions_walker ( Node node,
void context 
)
static

Definition at line 1018 of file clauses.c.

1019{
1020 if (node == NULL)
1021 return false;
1022 if (IsA(node, Aggref))
1023 {
1024 /* an aggregate could return non-null with null input */
1025 return true;
1026 }
1027 if (IsA(node, GroupingFunc))
1028 {
1029 /*
1030 * A GroupingFunc doesn't evaluate its arguments, and therefore must
1031 * be treated as nonstrict.
1032 */
1033 return true;
1034 }
1035 if (IsA(node, WindowFunc))
1036 {
1037 /* a window function could return non-null with null input */
1038 return true;
1039 }
1040 if (IsA(node, SubscriptingRef))
1041 {
1042 SubscriptingRef *sbsref = (SubscriptingRef *) node;
1044
1045 /* Subscripting assignment is always presumed nonstrict */
1046 if (sbsref->refassgnexpr != NULL)
1047 return true;
1048 /* Otherwise we must look up the subscripting support methods */
1049 sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
1050 if (!(sbsroutines && sbsroutines->fetch_strict))
1051 return true;
1052 /* else fall through to check args */
1053 }
1054 if (IsA(node, DistinctExpr))
1055 {
1056 /* IS DISTINCT FROM is inherently non-strict */
1057 return true;
1058 }
1059 if (IsA(node, NullIfExpr))
1060 {
1061 /* NULLIF is inherently non-strict */
1062 return true;
1063 }
1064 if (IsA(node, BoolExpr))
1065 {
1066 BoolExpr *expr = (BoolExpr *) node;
1067
1068 switch (expr->boolop)
1069 {
1070 case AND_EXPR:
1071 case OR_EXPR:
1072 /* AND, OR are inherently non-strict */
1073 return true;
1074 default:
1075 break;
1076 }
1077 }
1078 if (IsA(node, SubLink))
1079 {
1080 /* In some cases a sublink might be strict, but in general not */
1081 return true;
1082 }
1083 if (IsA(node, SubPlan))
1084 return true;
1085 if (IsA(node, AlternativeSubPlan))
1086 return true;
1087 if (IsA(node, FieldStore))
1088 return true;
1089 if (IsA(node, CoerceViaIO))
1090 {
1091 /*
1092 * CoerceViaIO is strict regardless of whether the I/O functions are,
1093 * so just go look at its argument; asking check_functions_in_node is
1094 * useless expense and could deliver the wrong answer.
1095 */
1097 context);
1098 }
1099 if (IsA(node, ArrayCoerceExpr))
1100 {
1101 /*
1102 * ArrayCoerceExpr is strict at the array level, regardless of what
1103 * the per-element expression is; so we should ignore elemexpr and
1104 * recurse only into the arg.
1105 */
1107 context);
1108 }
1109 if (IsA(node, CaseExpr))
1110 return true;
1111 if (IsA(node, ArrayExpr))
1112 return true;
1113 if (IsA(node, RowExpr))
1114 return true;
1115 if (IsA(node, RowCompareExpr))
1116 return true;
1117 if (IsA(node, CoalesceExpr))
1118 return true;
1119 if (IsA(node, MinMaxExpr))
1120 return true;
1121 if (IsA(node, XmlExpr))
1122 return true;
1123 if (IsA(node, NullTest))
1124 return true;
1125 if (IsA(node, BooleanTest))
1126 return true;
1127 if (IsA(node, JsonConstructorExpr))
1128 return true;
1129
1130 /* Check other function-containing nodes */
1132 context))
1133 return true;
1134
1136 context);
1137}
static bool contain_nonstrict_functions_checker(Oid func_id, void *context)
Definition clauses.c:1012

References AND_EXPR, arg, BoolExpr::boolop, check_functions_in_node(), contain_nonstrict_functions_checker(), contain_nonstrict_functions_walker(), expression_tree_walker, fb(), getSubscriptingRoutines(), IsA, OR_EXPR, and SubscriptingRef::refassgnexpr.

Referenced by contain_nonstrict_functions(), and contain_nonstrict_functions_walker().

◆ contain_subplans()

bool contain_subplans ( Node clause)

◆ contain_subplans_walker()

static bool contain_subplans_walker ( Node node,
void context 
)
static

Definition at line 349 of file clauses.c.

350{
351 if (node == NULL)
352 return false;
353 if (IsA(node, SubPlan) ||
354 IsA(node, AlternativeSubPlan) ||
355 IsA(node, SubLink))
356 return true; /* abort the tree traversal and return true */
357 return expression_tree_walker(node, contain_subplans_walker, context);
358}

References contain_subplans_walker(), expression_tree_walker, fb(), and IsA.

Referenced by contain_subplans(), and contain_subplans_walker().

◆ contain_volatile_functions()

bool contain_volatile_functions ( Node clause)

Definition at line 551 of file clauses.c.

552{
554}
static bool contain_volatile_functions_walker(Node *node, void *context)
Definition clauses.c:563

References contain_volatile_functions_walker(), and fb().

Referenced by apply_child_basequals(), ATExecAddColumn(), check_hashjoinable(), check_mergejoinable(), check_output_expressions(), compute_semijoin_info(), contain_volatile_functions_after_planning(), convert_ANY_sublink_to_join(), convert_EXISTS_sublink_to_join(), convert_EXISTS_to_ANY(), convert_VALUES_to_ANY(), CopyFrom(), create_agg_clause_infos(), distribute_qual_to_rels(), DomainHasConstraints(), estimate_num_groups(), ExecInitWindowAgg(), expand_indexqual_rowcompare(), find_compatible_agg(), find_simplified_clause(), get_eclass_for_sort_expr(), get_memoize_path(), group_similar_or_args(), initialize_peragg(), inline_function(), inline_function_in_from(), is_pseudo_constant_clause(), is_pseudo_constant_clause_relids(), is_pseudo_constant_for_index(), is_safe_restriction_clause_for(), is_simple_subquery(), is_simple_values(), IsBinaryTidClause(), IsTidEqualAnyClause(), make_sort_input_target(), mark_nullable_by_grouping(), match_clause_to_ordering_op(), match_clause_to_partition_key(), match_opclause_to_indexcol(), match_orclause_to_indexcol(), match_rowcompare_to_indexcol(), match_saopclause_to_indexcol(), paraminfo_get_equal_hashops(), qual_is_pushdown_safe(), remove_unused_subquery_outputs(), SS_process_ctes(), and subquery_planner().

◆ contain_volatile_functions_after_planning()

bool contain_volatile_functions_after_planning ( Expr expr)

Definition at line 672 of file clauses.c.

673{
674 /* We assume here that expression_planner() won't scribble on its input */
675 expr = expression_planner(expr);
676
677 /* Now we can search for volatile functions */
678 return contain_volatile_functions((Node *) expr);
679}

References contain_volatile_functions(), and expression_planner().

Referenced by transformForPortionOfClause().

◆ contain_volatile_functions_checker()

static bool contain_volatile_functions_checker ( Oid  func_id,
void context 
)
static

Definition at line 557 of file clauses.c.

558{
560}

References fb(), and func_volatile().

Referenced by contain_volatile_functions_walker().

◆ contain_volatile_functions_not_nextval()

bool contain_volatile_functions_not_nextval ( Node clause)

Definition at line 686 of file clauses.c.

687{
689}
static bool contain_volatile_functions_not_nextval_walker(Node *node, void *context)
Definition clauses.c:699

References contain_volatile_functions_not_nextval_walker(), and fb().

Referenced by BeginCopyFrom().

◆ contain_volatile_functions_not_nextval_checker()

static bool contain_volatile_functions_not_nextval_checker ( Oid  func_id,
void context 
)
static

Definition at line 692 of file clauses.c.

693{
694 return (func_id != F_NEXTVAL &&
696}

References fb(), and func_volatile().

Referenced by contain_volatile_functions_not_nextval_walker().

◆ contain_volatile_functions_not_nextval_walker()

static bool contain_volatile_functions_not_nextval_walker ( Node node,
void context 
)
static

Definition at line 699 of file clauses.c.

700{
701 if (node == NULL)
702 return false;
703 /* Check for volatile functions in node itself */
706 context))
707 return true;
708
709 /*
710 * See notes in contain_mutable_functions_walker about why we treat
711 * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
712 * SQLValueFunction is stable. Hence, none of them are of interest here.
713 * Also, since we're intentionally ignoring nextval(), presumably we
714 * should ignore NextValueExpr.
715 */
716
717 /* Recurse to check arguments */
718 if (IsA(node, Query))
719 {
720 /* Recurse into subselects */
721 return query_tree_walker((Query *) node,
723 context, 0);
724 }
725 return expression_tree_walker(node,
727 context);
728}
static bool contain_volatile_functions_not_nextval_checker(Oid func_id, void *context)
Definition clauses.c:692

References check_functions_in_node(), contain_volatile_functions_not_nextval_checker(), contain_volatile_functions_not_nextval_walker(), expression_tree_walker, fb(), IsA, and query_tree_walker.

Referenced by contain_volatile_functions_not_nextval(), and contain_volatile_functions_not_nextval_walker().

◆ contain_volatile_functions_walker()

static bool contain_volatile_functions_walker ( Node node,
void context 
)
static

Definition at line 563 of file clauses.c.

564{
565 if (node == NULL)
566 return false;
567 /* Check for volatile functions in node itself */
569 context))
570 return true;
571
572 if (IsA(node, NextValueExpr))
573 {
574 /* NextValueExpr is volatile */
575 return true;
576 }
577
578 if (IsA(node, RestrictInfo))
579 {
580 RestrictInfo *rinfo = (RestrictInfo *) node;
581
582 /*
583 * For RestrictInfo, check if we've checked the volatility of it
584 * before. If so, we can just use the cached value and not bother
585 * checking it again. Otherwise, check it and cache if whether we
586 * found any volatile functions.
587 */
588 if (rinfo->has_volatile == VOLATILITY_NOVOLATILE)
589 return false;
590 else if (rinfo->has_volatile == VOLATILITY_VOLATILE)
591 return true;
592 else
593 {
594 bool hasvolatile;
595
597 context);
598 if (hasvolatile)
599 rinfo->has_volatile = VOLATILITY_VOLATILE;
600 else
601 rinfo->has_volatile = VOLATILITY_NOVOLATILE;
602
603 return hasvolatile;
604 }
605 }
606
607 if (IsA(node, PathTarget))
608 {
609 PathTarget *target = (PathTarget *) node;
610
611 /*
612 * We also do caching for PathTarget the same as we do above for
613 * RestrictInfos.
614 */
616 return false;
617 else if (target->has_volatile_expr == VOLATILITY_VOLATILE)
618 return true;
619 else
620 {
621 bool hasvolatile;
622
624 context);
625
626 if (hasvolatile)
628 else
630
631 return hasvolatile;
632 }
633 }
634
635 /*
636 * See notes in contain_mutable_functions_walker about why we treat
637 * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while
638 * SQLValueFunction is stable. Hence, none of them are of interest here.
639 */
640
641 /* Recurse to check arguments */
642 if (IsA(node, Query))
643 {
644 /* Recurse into subselects */
645 return query_tree_walker((Query *) node,
647 context, 0);
648 }
650 context);
651}
static bool contain_volatile_functions_checker(Oid func_id, void *context)
Definition clauses.c:557
@ VOLATILITY_NOVOLATILE
Definition pathnodes.h:1845
@ VOLATILITY_VOLATILE
Definition pathnodes.h:1844
VolatileFunctionStatus has_volatile_expr
Definition pathnodes.h:1890
List * exprs
Definition pathnodes.h:1878
Expr * clause
Definition pathnodes.h:2901

References check_functions_in_node(), RestrictInfo::clause, contain_volatile_functions_checker(), contain_volatile_functions_walker(), expression_tree_walker, PathTarget::exprs, fb(), PathTarget::has_volatile_expr, IsA, query_tree_walker, VOLATILITY_NOVOLATILE, and VOLATILITY_VOLATILE.

Referenced by contain_volatile_functions(), and contain_volatile_functions_walker().

◆ contain_window_function()

bool contain_window_function ( Node clause)

Definition at line 231 of file clauses.c.

232{
233 return contain_windowfuncs(clause);
234}
bool contain_windowfuncs(Node *node)

References contain_windowfuncs().

Referenced by get_eclass_for_sort_expr(), and mark_nullable_by_grouping().

◆ convert_saop_to_hashed_saop()

void convert_saop_to_hashed_saop ( Node node)

Definition at line 2533 of file clauses.c.

2534{
2536}
static bool convert_saop_to_hashed_saop_walker(Node *node, void *context)
Definition clauses.c:2539

References convert_saop_to_hashed_saop_walker(), and fb().

Referenced by preprocess_expression().

◆ convert_saop_to_hashed_saop_walker()

static bool convert_saop_to_hashed_saop_walker ( Node node,
void context 
)
static

Definition at line 2539 of file clauses.c.

2540{
2541 if (node == NULL)
2542 return false;
2543
2544 if (IsA(node, ScalarArrayOpExpr))
2545 {
2546 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) node;
2547 Expr *arrayarg = (Expr *) lsecond(saop->args);
2550
2551 if (arrayarg && IsA(arrayarg, Const) &&
2552 !((Const *) arrayarg)->constisnull)
2553 {
2554 if (saop->useOr)
2555 {
2558 {
2559 Datum arrdatum = ((Const *) arrayarg)->constvalue;
2561 int nitems;
2562
2563 /*
2564 * Only fill in the hash functions if the array looks
2565 * large enough for it to be worth hashing instead of
2566 * doing a linear search.
2567 */
2568 nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
2569
2571 {
2572 /* Looks good. Fill in the hash functions */
2573 saop->hashfuncid = lefthashfunc;
2574 }
2575 return false;
2576 }
2577 }
2578 else /* !saop->useOr */
2579 {
2580 Oid negator = get_negator(saop->opno);
2581
2582 /*
2583 * Check if this is a NOT IN using an operator whose negator
2584 * is hashable. If so we can still build a hash table and
2585 * just ensure the lookup items are not in the hash table.
2586 */
2587 if (OidIsValid(negator) &&
2590 {
2591 Datum arrdatum = ((Const *) arrayarg)->constvalue;
2593 int nitems;
2594
2595 /*
2596 * Only fill in the hash functions if the array looks
2597 * large enough for it to be worth hashing instead of
2598 * doing a linear search.
2599 */
2600 nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
2601
2603 {
2604 /* Looks good. Fill in the hash functions */
2605 saop->hashfuncid = lefthashfunc;
2606
2607 /*
2608 * Also set the negfuncid. The executor will need
2609 * that to perform hashtable lookups.
2610 */
2611 saop->negfuncid = get_opcode(negator);
2612 }
2613 return false;
2614 }
2615 }
2616 }
2617 }
2618
2620}
int ArrayGetNItems(int ndim, const int *dims)
Definition arrayutils.c:57
#define MIN_ARRAY_SIZE_FOR_HASHED_SAOP
Definition clauses.c:2515
#define nitems(x)
Definition indent.h:31
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition lsyscache.c:577
Oid get_negator(Oid opno)
Definition lsyscache.c:1726

References ScalarArrayOpExpr::args, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), convert_saop_to_hashed_saop_walker(), DatumGetPointer(), expression_tree_walker, fb(), get_negator(), get_op_hash_functions(), get_opcode(), IsA, lsecond, MIN_ARRAY_SIZE_FOR_HASHED_SAOP, nitems, OidIsValid, ScalarArrayOpExpr::opno, and ScalarArrayOpExpr::useOr.

Referenced by convert_saop_to_hashed_saop(), and convert_saop_to_hashed_saop_walker().

◆ ece_function_is_safe()

static bool ece_function_is_safe ( Oid  funcid,
eval_const_expressions_context context 
)
static

Definition at line 4173 of file clauses.c.

4174{
4175 char provolatile = func_volatile(funcid);
4176
4177 /*
4178 * Ordinarily we are only allowed to simplify immutable functions. But for
4179 * purposes of estimation, we consider it okay to simplify functions that
4180 * are merely stable; the risk that the result might change from planning
4181 * time to execution time is worth taking in preference to not being able
4182 * to estimate the value at all.
4183 */
4185 return true;
4186 if (context->estimate && provolatile == PROVOLATILE_STABLE)
4187 return true;
4188 return false;
4189}

References eval_const_expressions_context::estimate, fb(), and func_volatile().

Referenced by eval_const_expressions_mutator().

◆ estimate_expression_value()

Node * estimate_expression_value ( PlannerInfo root,
Node node 
)

◆ eval_const_expressions()

Node * eval_const_expressions ( PlannerInfo root,
Node node 
)

Definition at line 2500 of file clauses.c.

2501{
2503
2504 if (root)
2505 context.boundParams = root->glob->boundParams; /* bound Params */
2506 else
2507 context.boundParams = NULL;
2508 context.root = root; /* for inlined-function dependencies */
2509 context.active_fns = NIL; /* nothing being recursively simplified */
2510 context.case_val = NULL; /* no CASE being examined */
2511 context.estimate = false; /* safe transformations only */
2512 return eval_const_expressions_mutator(node, &context);
2513}

References eval_const_expressions_context::active_fns, eval_const_expressions_context::boundParams, eval_const_expressions_context::case_val, eval_const_expressions_context::estimate, eval_const_expressions_mutator(), fb(), NIL, eval_const_expressions_context::root, and root.

Referenced by apply_child_basequals(), ATExecAttachPartition(), ConstraintImpliedByRelConstraint(), convert_EXISTS_to_ANY(), convert_VALUES_to_ANY(), DoCopy(), expand_insert_targetlist(), expression_planner(), expression_planner_with_deps(), extended_statistics_update(), fetch_statentries_for_relation(), get_proposed_default_constraint(), get_relation_constraints(), get_relation_info(), get_relation_statistics(), infer_arbiter_indexes(), preprocess_expression(), preprocess_function_rtes(), process_implied_equality(), RelationBuildPartitionKey(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), simplify_EXISTS_query(), and SplitPartitionMoveRows().

◆ eval_const_expressions_mutator()

static Node * eval_const_expressions_mutator ( Node node,
eval_const_expressions_context context 
)
static

Definition at line 2686 of file clauses.c.

2688{
2689
2690 /* since this function recurses, it could be driven to stack overflow */
2692
2693 if (node == NULL)
2694 return NULL;
2695 switch (nodeTag(node))
2696 {
2697 case T_Param:
2698 {
2699 Param *param = (Param *) node;
2700 ParamListInfo paramLI = context->boundParams;
2701
2702 /* Look to see if we've been given a value for this Param */
2703 if (param->paramkind == PARAM_EXTERN &&
2704 paramLI != NULL &&
2705 param->paramid > 0 &&
2706 param->paramid <= paramLI->numParams)
2707 {
2710
2711 /*
2712 * Give hook a chance in case parameter is dynamic. Tell
2713 * it that this fetch is speculative, so it should avoid
2714 * erroring out if parameter is unavailable.
2715 */
2716 if (paramLI->paramFetch != NULL)
2717 prm = paramLI->paramFetch(paramLI, param->paramid,
2718 true, &prmdata);
2719 else
2720 prm = &paramLI->params[param->paramid - 1];
2721
2722 /*
2723 * We don't just check OidIsValid, but insist that the
2724 * fetched type match the Param, just in case the hook did
2725 * something unexpected. No need to throw an error here
2726 * though; leave that for runtime.
2727 */
2728 if (OidIsValid(prm->ptype) &&
2729 prm->ptype == param->paramtype)
2730 {
2731 /* OK to substitute parameter value? */
2732 if (context->estimate ||
2733 (prm->pflags & PARAM_FLAG_CONST))
2734 {
2735 /*
2736 * Return a Const representing the param value.
2737 * Must copy pass-by-ref datatypes, since the
2738 * Param might be in a memory context
2739 * shorter-lived than our output plan should be.
2740 */
2741 int16 typLen;
2742 bool typByVal;
2743 Datum pval;
2744 Const *con;
2745
2747 &typLen, &typByVal);
2748 if (prm->isnull || typByVal)
2749 pval = prm->value;
2750 else
2751 pval = datumCopy(prm->value, typByVal, typLen);
2752 con = makeConst(param->paramtype,
2753 param->paramtypmod,
2754 param->paramcollid,
2755 (int) typLen,
2756 pval,
2757 prm->isnull,
2758 typByVal);
2759 con->location = param->location;
2760 return (Node *) con;
2761 }
2762 }
2763 }
2764
2765 /*
2766 * Not replaceable, so just copy the Param (no need to
2767 * recurse)
2768 */
2769 return (Node *) copyObject(param);
2770 }
2771 case T_WindowFunc:
2772 {
2773 WindowFunc *expr = (WindowFunc *) node;
2774 Oid funcid = expr->winfnoid;
2775 List *args;
2776 Expr *aggfilter;
2779
2780 /*
2781 * We can't really simplify a WindowFunc node, but we mustn't
2782 * just fall through to the default processing, because we
2783 * have to apply expand_function_arguments to its argument
2784 * list. That takes care of inserting default arguments and
2785 * expanding named-argument notation.
2786 */
2789 elog(ERROR, "cache lookup failed for function %u", funcid);
2790
2792 false, expr->wintype,
2793 func_tuple);
2794
2796
2797 /* Now, recursively simplify the args (which are a List) */
2798 args = (List *)
2801 context);
2802 /* ... and the filter expression, which isn't */
2803 aggfilter = (Expr *)
2805 context);
2806
2807 /* And build the replacement WindowFunc node */
2809 newexpr->winfnoid = expr->winfnoid;
2810 newexpr->wintype = expr->wintype;
2811 newexpr->wincollid = expr->wincollid;
2812 newexpr->inputcollid = expr->inputcollid;
2813 newexpr->args = args;
2814 newexpr->aggfilter = aggfilter;
2815 newexpr->runCondition = expr->runCondition;
2816 newexpr->winref = expr->winref;
2817 newexpr->winstar = expr->winstar;
2818 newexpr->winagg = expr->winagg;
2820 newexpr->location = expr->location;
2821
2822 return (Node *) newexpr;
2823 }
2824 case T_FuncExpr:
2825 {
2826 FuncExpr *expr = (FuncExpr *) node;
2827 List *args = expr->args;
2828 Expr *simple;
2830
2831 /*
2832 * Code for op/func reduction is pretty bulky, so split it out
2833 * as a separate function. Note: exprTypmod normally returns
2834 * -1 for a FuncExpr, but not when the node is recognizably a
2835 * length coercion; we want to preserve the typmod in the
2836 * eventual Const if so.
2837 */
2838 simple = simplify_function(expr->funcid,
2839 expr->funcresulttype,
2840 exprTypmod(node),
2841 expr->funccollid,
2842 expr->inputcollid,
2843 &args,
2844 expr->funcvariadic,
2845 true,
2846 true,
2847 context);
2848 if (simple) /* successfully simplified it */
2849 return (Node *) simple;
2850
2851 /*
2852 * The expression cannot be simplified any further, so build
2853 * and return a replacement FuncExpr node using the
2854 * possibly-simplified arguments. Note that we have also
2855 * converted the argument list to positional notation.
2856 */
2858 newexpr->funcid = expr->funcid;
2859 newexpr->funcresulttype = expr->funcresulttype;
2860 newexpr->funcretset = expr->funcretset;
2861 newexpr->funcvariadic = expr->funcvariadic;
2862 newexpr->funcformat = expr->funcformat;
2863 newexpr->funccollid = expr->funccollid;
2864 newexpr->inputcollid = expr->inputcollid;
2865 newexpr->args = args;
2866 newexpr->location = expr->location;
2867 return (Node *) newexpr;
2868 }
2869 case T_Aggref:
2870 node = ece_generic_processing(node);
2871 if (context->root != NULL)
2872 return simplify_aggref((Aggref *) node, context);
2873 return node;
2874 case T_OpExpr:
2875 {
2876 OpExpr *expr = (OpExpr *) node;
2877 List *args = expr->args;
2878 Expr *simple;
2879 OpExpr *newexpr;
2880
2881 /*
2882 * Need to get OID of underlying function. Okay to scribble
2883 * on input to this extent.
2884 */
2885 set_opfuncid(expr);
2886
2887 /*
2888 * Code for op/func reduction is pretty bulky, so split it out
2889 * as a separate function.
2890 */
2891 simple = simplify_function(expr->opfuncid,
2892 expr->opresulttype, -1,
2893 expr->opcollid,
2894 expr->inputcollid,
2895 &args,
2896 false,
2897 true,
2898 true,
2899 context);
2900 if (simple) /* successfully simplified it */
2901 return (Node *) simple;
2902
2903 /*
2904 * If the operator is boolean equality or inequality, we know
2905 * how to simplify cases involving one constant and one
2906 * non-constant argument.
2907 */
2908 if (expr->opno == BooleanEqualOperator ||
2910 {
2911 simple = (Expr *) simplify_boolean_equality(expr->opno,
2912 args);
2913 if (simple) /* successfully simplified it */
2914 return (Node *) simple;
2915 }
2916
2917 /*
2918 * The expression cannot be simplified any further, so build
2919 * and return a replacement OpExpr node using the
2920 * possibly-simplified arguments.
2921 */
2923 newexpr->opno = expr->opno;
2924 newexpr->opfuncid = expr->opfuncid;
2925 newexpr->opresulttype = expr->opresulttype;
2926 newexpr->opretset = expr->opretset;
2927 newexpr->opcollid = expr->opcollid;
2928 newexpr->inputcollid = expr->inputcollid;
2929 newexpr->args = args;
2930 newexpr->location = expr->location;
2931 return (Node *) newexpr;
2932 }
2933 case T_DistinctExpr:
2934 {
2935 DistinctExpr *expr = (DistinctExpr *) node;
2936 List *args;
2937 ListCell *arg;
2938 bool has_null_input = false;
2939 bool all_null_input = true;
2940 bool has_nonconst_input = false;
2941 bool has_nullable_nonconst = false;
2942 Expr *simple;
2944
2945 /*
2946 * Reduce constants in the DistinctExpr's arguments. We know
2947 * args is either NIL or a List node, so we can call
2948 * expression_tree_mutator directly rather than recursing to
2949 * self.
2950 */
2951 args = (List *) expression_tree_mutator((Node *) expr->args,
2953 context);
2954
2955 /*
2956 * We must do our own check for NULLs because DistinctExpr has
2957 * different results for NULL input than the underlying
2958 * operator does. We also check if any non-constant input is
2959 * potentially nullable.
2960 */
2961 foreach(arg, args)
2962 {
2963 if (IsA(lfirst(arg), Const))
2964 {
2967 }
2968 else
2969 {
2970 has_nonconst_input = true;
2971 all_null_input = false;
2972
2973 if (!has_nullable_nonconst &&
2974 !expr_is_nonnullable(context->root,
2975 (Expr *) lfirst(arg),
2977 has_nullable_nonconst = true;
2978 }
2979 }
2980
2981 if (!has_nonconst_input)
2982 {
2983 /*
2984 * All inputs are constants. We can optimize this out
2985 * completely.
2986 */
2987
2988 /* all nulls? then not distinct */
2989 if (all_null_input)
2990 return makeBoolConst(false, false);
2991
2992 /* one null? then distinct */
2993 if (has_null_input)
2994 return makeBoolConst(true, false);
2995
2996 /* otherwise try to evaluate the '=' operator */
2997 /* (NOT okay to try to inline it, though!) */
2998
2999 /*
3000 * Need to get OID of underlying function. Okay to
3001 * scribble on input to this extent.
3002 */
3003 set_opfuncid((OpExpr *) expr); /* rely on struct
3004 * equivalence */
3005
3006 /*
3007 * Code for op/func reduction is pretty bulky, so split it
3008 * out as a separate function.
3009 */
3010 simple = simplify_function(expr->opfuncid,
3011 expr->opresulttype, -1,
3012 expr->opcollid,
3013 expr->inputcollid,
3014 &args,
3015 false,
3016 false,
3017 false,
3018 context);
3019 if (simple) /* successfully simplified it */
3020 {
3021 /*
3022 * Since the underlying operator is "=", must negate
3023 * its result
3024 */
3025 Const *csimple = castNode(Const, simple);
3026
3027 csimple->constvalue =
3028 BoolGetDatum(!DatumGetBool(csimple->constvalue));
3029 return (Node *) csimple;
3030 }
3031 }
3032 else if (!has_nullable_nonconst)
3033 {
3034 /*
3035 * There are non-constant inputs, but since all of them
3036 * are proven non-nullable, "IS DISTINCT FROM" semantics
3037 * are much simpler.
3038 */
3039
3040 OpExpr *eqexpr;
3041
3042 /*
3043 * If one input is an explicit NULL constant, and the
3044 * other is a non-nullable expression, the result is
3045 * always TRUE.
3046 */
3047 if (has_null_input)
3048 return makeBoolConst(true, false);
3049
3050 /*
3051 * Otherwise, both inputs are known non-nullable. In this
3052 * case, "IS DISTINCT FROM" is equivalent to the standard
3053 * inequality operator (usually "<>"). We convert this to
3054 * an OpExpr, which is a more efficient representation for
3055 * the planner. It can enable the use of partial indexes
3056 * and constraint exclusion. Furthermore, if the clause
3057 * is negated (ie, "IS NOT DISTINCT FROM"), the resulting
3058 * "=" operator can allow the planner to use index scans,
3059 * merge joins, hash joins, and EC-based qual deductions.
3060 */
3062 eqexpr->opno = expr->opno;
3063 eqexpr->opfuncid = expr->opfuncid;
3064 eqexpr->opresulttype = BOOLOID;
3065 eqexpr->opretset = expr->opretset;
3066 eqexpr->opcollid = expr->opcollid;
3067 eqexpr->inputcollid = expr->inputcollid;
3068 eqexpr->args = args;
3069 eqexpr->location = expr->location;
3070
3072 context);
3073 }
3074 else if (has_null_input)
3075 {
3076 /*
3077 * One input is a nullable non-constant expression, and
3078 * the other is an explicit NULL constant. We can
3079 * transform this to a NullTest with !argisrow, which is
3080 * much more amenable to optimization.
3081 */
3082
3084
3085 nt->arg = (Expr *) (IsA(linitial(args), Const) ?
3086 lsecond(args) : linitial(args));
3087 nt->nulltesttype = IS_NOT_NULL;
3088
3089 /*
3090 * argisrow = false is correct whether or not arg is
3091 * composite
3092 */
3093 nt->argisrow = false;
3094 nt->location = expr->location;
3095
3096 return eval_const_expressions_mutator((Node *) nt, context);
3097 }
3098
3099 /*
3100 * The expression cannot be simplified any further, so build
3101 * and return a replacement DistinctExpr node using the
3102 * possibly-simplified arguments.
3103 */
3105 newexpr->opno = expr->opno;
3106 newexpr->opfuncid = expr->opfuncid;
3107 newexpr->opresulttype = expr->opresulttype;
3108 newexpr->opretset = expr->opretset;
3109 newexpr->opcollid = expr->opcollid;
3110 newexpr->inputcollid = expr->inputcollid;
3111 newexpr->args = args;
3112 newexpr->location = expr->location;
3113 return (Node *) newexpr;
3114 }
3115 case T_NullIfExpr:
3116 {
3117 NullIfExpr *expr;
3118 ListCell *arg;
3119 bool has_nonconst_input = false;
3120
3121 /* Copy the node and const-simplify its arguments */
3122 expr = (NullIfExpr *) ece_generic_processing(node);
3123
3124 /* If either argument is NULL they can't be equal */
3125 foreach(arg, expr->args)
3126 {
3127 if (!IsA(lfirst(arg), Const))
3128 has_nonconst_input = true;
3129 else if (((Const *) lfirst(arg))->constisnull)
3130 return (Node *) linitial(expr->args);
3131 }
3132
3133 /*
3134 * Need to get OID of underlying function before checking if
3135 * the function is OK to evaluate.
3136 */
3137 set_opfuncid((OpExpr *) expr);
3138
3139 if (!has_nonconst_input &&
3140 ece_function_is_safe(expr->opfuncid, context))
3141 return ece_evaluate_expr(expr);
3142
3143 return (Node *) expr;
3144 }
3146 {
3147 ScalarArrayOpExpr *saop;
3148
3149 /* Copy the node and const-simplify its arguments */
3151
3152 /* Make sure we know underlying function */
3153 set_sa_opfuncid(saop);
3154
3155 /*
3156 * If all arguments are Consts, and it's a safe function, we
3157 * can fold to a constant
3158 */
3159 if (ece_all_arguments_const(saop) &&
3160 ece_function_is_safe(saop->opfuncid, context))
3161 return ece_evaluate_expr(saop);
3162 return (Node *) saop;
3163 }
3164 case T_BoolExpr:
3165 {
3166 BoolExpr *expr = (BoolExpr *) node;
3167
3168 switch (expr->boolop)
3169 {
3170 case OR_EXPR:
3171 {
3172 List *newargs;
3173 bool haveNull = false;
3174 bool forceTrue = false;
3175
3177 context,
3178 &haveNull,
3179 &forceTrue);
3180 if (forceTrue)
3181 return makeBoolConst(true, false);
3182 if (haveNull)
3184 makeBoolConst(false, true));
3185 /* If all the inputs are FALSE, result is FALSE */
3186 if (newargs == NIL)
3187 return makeBoolConst(false, false);
3188
3189 /*
3190 * If only one nonconst-or-NULL input, it's the
3191 * result
3192 */
3193 if (list_length(newargs) == 1)
3194 return (Node *) linitial(newargs);
3195 /* Else we still need an OR node */
3196 return (Node *) make_orclause(newargs);
3197 }
3198 case AND_EXPR:
3199 {
3200 List *newargs;
3201 bool haveNull = false;
3202 bool forceFalse = false;
3203
3205 context,
3206 &haveNull,
3207 &forceFalse);
3208 if (forceFalse)
3209 return makeBoolConst(false, false);
3210 if (haveNull)
3212 makeBoolConst(false, true));
3213 /* If all the inputs are TRUE, result is TRUE */
3214 if (newargs == NIL)
3215 return makeBoolConst(true, false);
3216
3217 /*
3218 * If only one nonconst-or-NULL input, it's the
3219 * result
3220 */
3221 if (list_length(newargs) == 1)
3222 return (Node *) linitial(newargs);
3223 /* Else we still need an AND node */
3224 return (Node *) make_andclause(newargs);
3225 }
3226 case NOT_EXPR:
3227 {
3228 Node *arg;
3229
3230 Assert(list_length(expr->args) == 1);
3232 context);
3233
3234 /*
3235 * Use negate_clause() to see if we can simplify
3236 * away the NOT.
3237 */
3238 return negate_clause(arg);
3239 }
3240 default:
3241 elog(ERROR, "unrecognized boolop: %d",
3242 (int) expr->boolop);
3243 break;
3244 }
3245 break;
3246 }
3247
3248 case T_JsonValueExpr:
3249 {
3250 JsonValueExpr *jve = (JsonValueExpr *) node;
3251 Node *raw_expr = (Node *) jve->raw_expr;
3252 Node *formatted_expr = (Node *) jve->formatted_expr;
3253
3254 /*
3255 * If we can fold formatted_expr to a constant, we can elide
3256 * the JsonValueExpr altogether. Otherwise we must process
3257 * raw_expr too. But JsonFormat is a flat node and requires
3258 * no simplification, only copying.
3259 */
3260 formatted_expr = eval_const_expressions_mutator(formatted_expr,
3261 context);
3262 if (formatted_expr && IsA(formatted_expr, Const))
3263 return formatted_expr;
3264
3265 raw_expr = eval_const_expressions_mutator(raw_expr, context);
3266
3267 return (Node *) makeJsonValueExpr((Expr *) raw_expr,
3268 (Expr *) formatted_expr,
3269 copyObject(jve->format));
3270 }
3271
3272 case T_SubPlan:
3274
3275 /*
3276 * Return a SubPlan unchanged --- too late to do anything with it.
3277 *
3278 * XXX should we ereport() here instead? Probably this routine
3279 * should never be invoked after SubPlan creation.
3280 */
3281 return node;
3282 case T_RelabelType:
3283 {
3284 RelabelType *relabel = (RelabelType *) node;
3285 Node *arg;
3286
3287 /* Simplify the input ... */
3289 context);
3290 /* ... and attach a new RelabelType node, if needed */
3291 return applyRelabelType(arg,
3292 relabel->resulttype,
3293 relabel->resulttypmod,
3294 relabel->resultcollid,
3295 relabel->relabelformat,
3296 relabel->location,
3297 true);
3298 }
3299 case T_CoerceViaIO:
3300 {
3301 CoerceViaIO *expr = (CoerceViaIO *) node;
3302 List *args;
3303 Oid outfunc;
3304 bool outtypisvarlena;
3305 Oid infunc;
3307 Expr *simple;
3309
3310 /* Make a List so we can use simplify_function */
3311 args = list_make1(expr->arg);
3312
3313 /*
3314 * CoerceViaIO represents calling the source type's output
3315 * function then the result type's input function. So, try to
3316 * simplify it as though it were a stack of two such function
3317 * calls. First we need to know what the functions are.
3318 *
3319 * Note that the coercion functions are assumed not to care
3320 * about input collation, so we just pass InvalidOid for that.
3321 */
3325 &infunc, &intypioparam);
3326
3327 simple = simplify_function(outfunc,
3328 CSTRINGOID, -1,
3329 InvalidOid,
3330 InvalidOid,
3331 &args,
3332 false,
3333 true,
3334 true,
3335 context);
3336 if (simple) /* successfully simplified output fn */
3337 {
3338 /*
3339 * Input functions may want 1 to 3 arguments. We always
3340 * supply all three, trusting that nothing downstream will
3341 * complain.
3342 */
3343 args = list_make3(simple,
3345 -1,
3346 InvalidOid,
3347 sizeof(Oid),
3349 false,
3350 true),
3352 -1,
3353 InvalidOid,
3354 sizeof(int32),
3355 Int32GetDatum(-1),
3356 false,
3357 true));
3358
3359 simple = simplify_function(infunc,
3360 expr->resulttype, -1,
3361 expr->resultcollid,
3362 InvalidOid,
3363 &args,
3364 false,
3365 false,
3366 true,
3367 context);
3368 if (simple) /* successfully simplified input fn */
3369 return (Node *) simple;
3370 }
3371
3372 /*
3373 * The expression cannot be simplified any further, so build
3374 * and return a replacement CoerceViaIO node using the
3375 * possibly-simplified argument.
3376 */
3378 newexpr->arg = (Expr *) linitial(args);
3379 newexpr->resulttype = expr->resulttype;
3380 newexpr->resultcollid = expr->resultcollid;
3381 newexpr->coerceformat = expr->coerceformat;
3382 newexpr->location = expr->location;
3383 return (Node *) newexpr;
3384 }
3385 case T_ArrayCoerceExpr:
3386 {
3389
3390 /*
3391 * Copy the node and const-simplify its arguments. We can't
3392 * use ece_generic_processing() here because we need to mess
3393 * with case_val only while processing the elemexpr.
3394 */
3395 memcpy(ac, node, sizeof(ArrayCoerceExpr));
3396 ac->arg = (Expr *)
3398 context);
3399
3400 /*
3401 * Set up for the CaseTestExpr node contained in the elemexpr.
3402 * We must prevent it from absorbing any outer CASE value.
3403 */
3404 save_case_val = context->case_val;
3405 context->case_val = NULL;
3406
3407 ac->elemexpr = (Expr *)
3409 context);
3410
3411 context->case_val = save_case_val;
3412
3413 /*
3414 * If constant argument and the per-element expression is
3415 * immutable, we can simplify the whole thing to a constant.
3416 * Exception: although contain_mutable_functions considers
3417 * CoerceToDomain immutable for historical reasons, let's not
3418 * do so here; this ensures coercion to an array-over-domain
3419 * does not apply the domain's constraints until runtime.
3420 */
3421 if (ac->arg && IsA(ac->arg, Const) &&
3422 ac->elemexpr && !IsA(ac->elemexpr, CoerceToDomain) &&
3423 !contain_mutable_functions((Node *) ac->elemexpr))
3424 return ece_evaluate_expr(ac);
3425
3426 return (Node *) ac;
3427 }
3428 case T_CollateExpr:
3429 {
3430 /*
3431 * We replace CollateExpr with RelabelType, so as to improve
3432 * uniformity of expression representation and thus simplify
3433 * comparison of expressions. Hence this looks very nearly
3434 * the same as the RelabelType case, and we can apply the same
3435 * optimizations to avoid unnecessary RelabelTypes.
3436 */
3437 CollateExpr *collate = (CollateExpr *) node;
3438 Node *arg;
3439
3440 /* Simplify the input ... */
3442 context);
3443 /* ... and attach a new RelabelType node, if needed */
3444 return applyRelabelType(arg,
3445 exprType(arg),
3446 exprTypmod(arg),
3447 collate->collOid,
3449 collate->location,
3450 true);
3451 }
3452 case T_CaseExpr:
3453 {
3454 /*----------
3455 * CASE expressions can be simplified if there are constant
3456 * condition clauses:
3457 * FALSE (or NULL): drop the alternative
3458 * TRUE: drop all remaining alternatives
3459 * If the first non-FALSE alternative is a constant TRUE,
3460 * we can simplify the entire CASE to that alternative's
3461 * expression. If there are no non-FALSE alternatives,
3462 * we simplify the entire CASE to the default result (ELSE).
3463 *
3464 * If we have a simple-form CASE with constant test
3465 * expression, we substitute the constant value for contained
3466 * CaseTestExpr placeholder nodes, so that we have the
3467 * opportunity to reduce constant test conditions. For
3468 * example this allows
3469 * CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
3470 * to reduce to 1 rather than drawing a divide-by-0 error.
3471 * Note that when the test expression is constant, we don't
3472 * have to include it in the resulting CASE; for example
3473 * CASE 0 WHEN x THEN y ELSE z END
3474 * is transformed by the parser to
3475 * CASE 0 WHEN CaseTestExpr = x THEN y ELSE z END
3476 * which we can simplify to
3477 * CASE WHEN 0 = x THEN y ELSE z END
3478 * It is not necessary for the executor to evaluate the "arg"
3479 * expression when executing the CASE, since any contained
3480 * CaseTestExprs that might have referred to it will have been
3481 * replaced by the constant.
3482 *----------
3483 */
3484 CaseExpr *caseexpr = (CaseExpr *) node;
3487 Node *newarg;
3488 List *newargs;
3489 bool const_true_cond;
3490 Node *defresult = NULL;
3491 ListCell *arg;
3492
3493 /* Simplify the test expression, if any */
3495 context);
3496
3497 /* Set up for contained CaseTestExpr nodes */
3498 save_case_val = context->case_val;
3499 if (newarg && IsA(newarg, Const))
3500 {
3501 context->case_val = newarg;
3502 newarg = NULL; /* not needed anymore, see above */
3503 }
3504 else
3505 context->case_val = NULL;
3506
3507 /* Simplify the WHEN clauses */
3508 newargs = NIL;
3509 const_true_cond = false;
3510 foreach(arg, caseexpr->args)
3511 {
3513 Node *casecond;
3515
3516 /* Simplify this alternative's test condition */
3518 context);
3519
3520 /*
3521 * If the test condition is constant FALSE (or NULL), then
3522 * drop this WHEN clause completely, without processing
3523 * the result.
3524 */
3525 if (casecond && IsA(casecond, Const))
3526 {
3528
3529 if (const_input->constisnull ||
3530 !DatumGetBool(const_input->constvalue))
3531 continue; /* drop alternative with FALSE cond */
3532 /* Else it's constant TRUE */
3533 const_true_cond = true;
3534 }
3535
3536 /* Simplify this alternative's result value */
3538 context);
3539
3540 /* If non-constant test condition, emit a new WHEN node */
3541 if (!const_true_cond)
3542 {
3544
3545 newcasewhen->expr = (Expr *) casecond;
3546 newcasewhen->result = (Expr *) caseresult;
3547 newcasewhen->location = oldcasewhen->location;
3549 continue;
3550 }
3551
3552 /*
3553 * Found a TRUE condition, so none of the remaining
3554 * alternatives can be reached. We treat the result as
3555 * the default result.
3556 */
3557 defresult = caseresult;
3558 break;
3559 }
3560
3561 /* Simplify the default result, unless we replaced it above */
3562 if (!const_true_cond)
3563 defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
3564 context);
3565
3566 context->case_val = save_case_val;
3567
3568 /*
3569 * If no non-FALSE alternatives, CASE reduces to the default
3570 * result
3571 */
3572 if (newargs == NIL)
3573 return defresult;
3574 /* Otherwise we need a new CASE node */
3576 newcase->casetype = caseexpr->casetype;
3577 newcase->casecollid = caseexpr->casecollid;
3578 newcase->arg = (Expr *) newarg;
3579 newcase->args = newargs;
3580 newcase->defresult = (Expr *) defresult;
3581 newcase->location = caseexpr->location;
3582 return (Node *) newcase;
3583 }
3584 case T_CaseTestExpr:
3585 {
3586 /*
3587 * If we know a constant test value for the current CASE
3588 * construct, substitute it for the placeholder. Else just
3589 * return the placeholder as-is.
3590 */
3591 if (context->case_val)
3592 return copyObject(context->case_val);
3593 else
3594 return copyObject(node);
3595 }
3596 case T_SubscriptingRef:
3597 case T_ArrayExpr:
3598 case T_RowExpr:
3599 case T_MinMaxExpr:
3600 {
3601 /*
3602 * Generic handling for node types whose own processing is
3603 * known to be immutable, and for which we need no smarts
3604 * beyond "simplify if all inputs are constants".
3605 *
3606 * Treating SubscriptingRef this way assumes that subscripting
3607 * fetch and assignment are both immutable. This constrains
3608 * type-specific subscripting implementations; maybe we should
3609 * relax it someday.
3610 *
3611 * Treating MinMaxExpr this way amounts to assuming that the
3612 * btree comparison function it calls is immutable; see the
3613 * reasoning in contain_mutable_functions_walker.
3614 */
3615
3616 /* Copy the node and const-simplify its arguments */
3617 node = ece_generic_processing(node);
3618 /* If all arguments are Consts, we can fold to a constant */
3619 if (ece_all_arguments_const(node))
3620 return ece_evaluate_expr(node);
3621 return node;
3622 }
3623 case T_CoalesceExpr:
3624 {
3627 List *newargs;
3628 ListCell *arg;
3629
3630 newargs = NIL;
3631 foreach(arg, coalesceexpr->args)
3632 {
3633 Node *e;
3634
3636 context);
3637
3638 /*
3639 * We can remove null constants from the list. For a
3640 * nonnullable expression, if it has not been preceded by
3641 * any non-null-constant expressions then it is the
3642 * result. Otherwise, it's the next argument, but we can
3643 * drop following arguments since they will never be
3644 * reached.
3645 */
3646 if (IsA(e, Const))
3647 {
3648 if (((Const *) e)->constisnull)
3649 continue; /* drop null constant */
3650 if (newargs == NIL)
3651 return e; /* first expr */
3653 break;
3654 }
3655 if (expr_is_nonnullable(context->root, (Expr *) e,
3657 {
3658 if (newargs == NIL)
3659 return e; /* first expr */
3661 break;
3662 }
3663
3665 }
3666
3667 /*
3668 * If all the arguments were constant null, the result is just
3669 * null
3670 */
3671 if (newargs == NIL)
3672 return (Node *) makeNullConst(coalesceexpr->coalescetype,
3673 -1,
3674 coalesceexpr->coalescecollid);
3675
3676 /*
3677 * If there's exactly one surviving argument, we no longer
3678 * need COALESCE at all: the result is that argument
3679 */
3680 if (list_length(newargs) == 1)
3681 return (Node *) linitial(newargs);
3682
3684 newcoalesce->coalescetype = coalesceexpr->coalescetype;
3685 newcoalesce->coalescecollid = coalesceexpr->coalescecollid;
3686 newcoalesce->args = newargs;
3687 newcoalesce->location = coalesceexpr->location;
3688 return (Node *) newcoalesce;
3689 }
3690 case T_SQLValueFunction:
3691 {
3692 /*
3693 * All variants of SQLValueFunction are stable, so if we are
3694 * estimating the expression's value, we should evaluate the
3695 * current function value. Otherwise just copy.
3696 */
3697 SQLValueFunction *svf = (SQLValueFunction *) node;
3698
3699 if (context->estimate)
3700 return (Node *) evaluate_expr((Expr *) svf,
3701 svf->type,
3702 svf->typmod,
3703 InvalidOid);
3704 else
3705 return copyObject((Node *) svf);
3706 }
3707 case T_FieldSelect:
3708 {
3709 /*
3710 * We can optimize field selection from a whole-row Var into a
3711 * simple Var. (This case won't be generated directly by the
3712 * parser, because ParseComplexProjection short-circuits it.
3713 * But it can arise while simplifying functions.) Also, we
3714 * can optimize field selection from a RowExpr construct, or
3715 * of course from a constant.
3716 *
3717 * However, replacing a whole-row Var in this way has a
3718 * pitfall: if we've already built the rel targetlist for the
3719 * source relation, then the whole-row Var is scheduled to be
3720 * produced by the relation scan, but the simple Var probably
3721 * isn't, which will lead to a failure in setrefs.c. This is
3722 * not a problem when handling simple single-level queries, in
3723 * which expression simplification always happens first. It
3724 * is a risk for lateral references from subqueries, though.
3725 * To avoid such failures, don't optimize uplevel references.
3726 *
3727 * We must also check that the declared type of the field is
3728 * still the same as when the FieldSelect was created --- this
3729 * can change if someone did ALTER COLUMN TYPE on the rowtype.
3730 * If it isn't, we skip the optimization; the case will
3731 * probably fail at runtime, but that's not our problem here.
3732 */
3733 FieldSelect *fselect = (FieldSelect *) node;
3735 Node *arg;
3736
3738 context);
3739 if (arg && IsA(arg, Var) &&
3740 ((Var *) arg)->varattno == InvalidAttrNumber &&
3741 ((Var *) arg)->varlevelsup == 0)
3742 {
3743 if (rowtype_field_matches(((Var *) arg)->vartype,
3744 fselect->fieldnum,
3745 fselect->resulttype,
3746 fselect->resulttypmod,
3747 fselect->resultcollid))
3748 {
3749 Var *newvar;
3750
3751 newvar = makeVar(((Var *) arg)->varno,
3752 fselect->fieldnum,
3753 fselect->resulttype,
3754 fselect->resulttypmod,
3755 fselect->resultcollid,
3756 ((Var *) arg)->varlevelsup);
3757 /* New Var has same OLD/NEW returning as old one */
3758 newvar->varreturningtype = ((Var *) arg)->varreturningtype;
3759 /* New Var is nullable by same rels as the old one */
3760 newvar->varnullingrels = ((Var *) arg)->varnullingrels;
3761 return (Node *) newvar;
3762 }
3763 }
3764 if (arg && IsA(arg, RowExpr))
3765 {
3766 RowExpr *rowexpr = (RowExpr *) arg;
3767
3768 if (fselect->fieldnum > 0 &&
3769 fselect->fieldnum <= list_length(rowexpr->args))
3770 {
3771 Node *fld = (Node *) list_nth(rowexpr->args,
3772 fselect->fieldnum - 1);
3773
3774 if (rowtype_field_matches(rowexpr->row_typeid,
3775 fselect->fieldnum,
3776 fselect->resulttype,
3777 fselect->resulttypmod,
3778 fselect->resultcollid) &&
3779 fselect->resulttype == exprType(fld) &&
3780 fselect->resulttypmod == exprTypmod(fld) &&
3781 fselect->resultcollid == exprCollation(fld))
3782 return fld;
3783 }
3784 }
3786 newfselect->arg = (Expr *) arg;
3787 newfselect->fieldnum = fselect->fieldnum;
3788 newfselect->resulttype = fselect->resulttype;
3789 newfselect->resulttypmod = fselect->resulttypmod;
3790 newfselect->resultcollid = fselect->resultcollid;
3791 if (arg && IsA(arg, Const))
3792 {
3793 Const *con = (Const *) arg;
3794
3796 newfselect->fieldnum,
3797 newfselect->resulttype,
3798 newfselect->resulttypmod,
3799 newfselect->resultcollid))
3801 }
3802 return (Node *) newfselect;
3803 }
3804 case T_NullTest:
3805 {
3806 NullTest *ntest = (NullTest *) node;
3808 Node *arg;
3809
3811 context);
3812 if (ntest->argisrow && arg && IsA(arg, RowExpr))
3813 {
3814 /*
3815 * We break ROW(...) IS [NOT] NULL into separate tests on
3816 * its component fields. This form is usually more
3817 * efficient to evaluate, as well as being more amenable
3818 * to optimization.
3819 */
3820 RowExpr *rarg = (RowExpr *) arg;
3821 List *newargs = NIL;
3822 ListCell *l;
3823
3824 foreach(l, rarg->args)
3825 {
3826 Node *relem = (Node *) lfirst(l);
3827
3828 /*
3829 * A constant field refutes the whole NullTest if it's
3830 * of the wrong nullness; else we can discard it.
3831 */
3832 if (relem && IsA(relem, Const))
3833 {
3834 Const *carg = (Const *) relem;
3835
3836 if (carg->constisnull ?
3837 (ntest->nulltesttype == IS_NOT_NULL) :
3838 (ntest->nulltesttype == IS_NULL))
3839 return makeBoolConst(false, false);
3840 continue;
3841 }
3842
3843 /*
3844 * A proven non-nullable field refutes the whole
3845 * NullTest if the test is IS NULL; else we can
3846 * discard it.
3847 */
3848 if (relem &&
3849 expr_is_nonnullable(context->root, (Expr *) relem,
3851 {
3852 if (ntest->nulltesttype == IS_NULL)
3853 return makeBoolConst(false, false);
3854 continue;
3855 }
3856
3857 /*
3858 * Else, make a scalar (argisrow == false) NullTest
3859 * for this field. Scalar semantics are required
3860 * because IS [NOT] NULL doesn't recurse; see comments
3861 * in ExecEvalRowNullInt().
3862 */
3864 newntest->arg = (Expr *) relem;
3865 newntest->nulltesttype = ntest->nulltesttype;
3866 newntest->argisrow = false;
3867 newntest->location = ntest->location;
3869 }
3870 /* If all the inputs were constants, result is TRUE */
3871 if (newargs == NIL)
3872 return makeBoolConst(true, false);
3873 /* If only one nonconst input, it's the result */
3874 if (list_length(newargs) == 1)
3875 return (Node *) linitial(newargs);
3876 /* Else we need an AND node */
3877 return (Node *) make_andclause(newargs);
3878 }
3879 if (!ntest->argisrow && arg && IsA(arg, Const))
3880 {
3881 Const *carg = (Const *) arg;
3882 bool result;
3883
3884 switch (ntest->nulltesttype)
3885 {
3886 case IS_NULL:
3887 result = carg->constisnull;
3888 break;
3889 case IS_NOT_NULL:
3890 result = !carg->constisnull;
3891 break;
3892 default:
3893 elog(ERROR, "unrecognized nulltesttype: %d",
3894 (int) ntest->nulltesttype);
3895 result = false; /* keep compiler quiet */
3896 break;
3897 }
3898
3899 return makeBoolConst(result, false);
3900 }
3901 if (!ntest->argisrow && arg &&
3902 expr_is_nonnullable(context->root, (Expr *) arg,
3904 {
3905 bool result;
3906
3907 switch (ntest->nulltesttype)
3908 {
3909 case IS_NULL:
3910 result = false;
3911 break;
3912 case IS_NOT_NULL:
3913 result = true;
3914 break;
3915 default:
3916 elog(ERROR, "unrecognized nulltesttype: %d",
3917 (int) ntest->nulltesttype);
3918 result = false; /* keep compiler quiet */
3919 break;
3920 }
3921
3922 return makeBoolConst(result, false);
3923 }
3924
3926 newntest->arg = (Expr *) arg;
3927 newntest->nulltesttype = ntest->nulltesttype;
3928 newntest->argisrow = ntest->argisrow;
3929 newntest->location = ntest->location;
3930 return (Node *) newntest;
3931 }
3932 case T_BooleanTest:
3933 {
3934 /*
3935 * This case could be folded into the generic handling used
3936 * for ArrayExpr etc. But because the simplification logic is
3937 * so trivial, applying evaluate_expr() to perform it would be
3938 * a heavy overhead. BooleanTest is probably common enough to
3939 * justify keeping this bespoke implementation.
3940 */
3941 BooleanTest *btest = (BooleanTest *) node;
3943 Node *arg;
3944
3946 context);
3947 if (arg && IsA(arg, Const))
3948 {
3949 /*
3950 * If arg is Const, simplify to constant.
3951 */
3952 Const *carg = (Const *) arg;
3953 bool result;
3954
3955 switch (btest->booltesttype)
3956 {
3957 case IS_TRUE:
3958 result = (!carg->constisnull &&
3959 DatumGetBool(carg->constvalue));
3960 break;
3961 case IS_NOT_TRUE:
3962 result = (carg->constisnull ||
3963 !DatumGetBool(carg->constvalue));
3964 break;
3965 case IS_FALSE:
3966 result = (!carg->constisnull &&
3967 !DatumGetBool(carg->constvalue));
3968 break;
3969 case IS_NOT_FALSE:
3970 result = (carg->constisnull ||
3971 DatumGetBool(carg->constvalue));
3972 break;
3973 case IS_UNKNOWN:
3974 result = carg->constisnull;
3975 break;
3976 case IS_NOT_UNKNOWN:
3977 result = !carg->constisnull;
3978 break;
3979 default:
3980 elog(ERROR, "unrecognized booltesttype: %d",
3981 (int) btest->booltesttype);
3982 result = false; /* keep compiler quiet */
3983 break;
3984 }
3985
3986 return makeBoolConst(result, false);
3987 }
3988 if (arg &&
3989 expr_is_nonnullable(context->root, (Expr *) arg,
3991 {
3992 /*
3993 * If arg is proven non-nullable, simplify to boolean
3994 * expression or constant.
3995 */
3996 switch (btest->booltesttype)
3997 {
3998 case IS_TRUE:
3999 case IS_NOT_FALSE:
4000 return arg;
4001
4002 case IS_FALSE:
4003 case IS_NOT_TRUE:
4004 return (Node *) make_notclause((Expr *) arg);
4005
4006 case IS_UNKNOWN:
4007 return makeBoolConst(false, false);
4008
4009 case IS_NOT_UNKNOWN:
4010 return makeBoolConst(true, false);
4011
4012 default:
4013 elog(ERROR, "unrecognized booltesttype: %d",
4014 (int) btest->booltesttype);
4015 break;
4016 }
4017 }
4018
4020 newbtest->arg = (Expr *) arg;
4021 newbtest->booltesttype = btest->booltesttype;
4022 newbtest->location = btest->location;
4023 return (Node *) newbtest;
4024 }
4025 case T_CoerceToDomain:
4026 {
4027 /*
4028 * If the domain currently has no constraints, we replace the
4029 * CoerceToDomain node with a simple RelabelType, which is
4030 * both far faster to execute and more amenable to later
4031 * optimization. We must then mark the plan as needing to be
4032 * rebuilt if the domain's constraints change.
4033 *
4034 * Also, in estimation mode, always replace CoerceToDomain
4035 * nodes, effectively assuming that the coercion will succeed.
4036 */
4039 Node *arg;
4040
4042 context);
4043 if (context->estimate ||
4044 !DomainHasConstraints(cdomain->resulttype, NULL))
4045 {
4046 /* Record dependency, if this isn't estimation mode */
4047 if (context->root && !context->estimate)
4049 cdomain->resulttype);
4050
4051 /* Generate RelabelType to substitute for CoerceToDomain */
4052 return applyRelabelType(arg,
4053 cdomain->resulttype,
4054 cdomain->resulttypmod,
4055 cdomain->resultcollid,
4056 cdomain->coercionformat,
4057 cdomain->location,
4058 true);
4059 }
4060
4062 newcdomain->arg = (Expr *) arg;
4063 newcdomain->resulttype = cdomain->resulttype;
4064 newcdomain->resulttypmod = cdomain->resulttypmod;
4065 newcdomain->resultcollid = cdomain->resultcollid;
4066 newcdomain->coercionformat = cdomain->coercionformat;
4067 newcdomain->location = cdomain->location;
4068 return (Node *) newcdomain;
4069 }
4070 case T_PlaceHolderVar:
4071
4072 /*
4073 * In estimation mode, just strip the PlaceHolderVar node
4074 * altogether; this amounts to estimating that the contained value
4075 * won't be forced to null by an outer join. In regular mode we
4076 * just use the default behavior (ie, simplify the expression but
4077 * leave the PlaceHolderVar node intact).
4078 */
4079 if (context->estimate)
4080 {
4081 PlaceHolderVar *phv = (PlaceHolderVar *) node;
4082
4083 return eval_const_expressions_mutator((Node *) phv->phexpr,
4084 context);
4085 }
4086 break;
4088 {
4090 Node *arg;
4092
4094 context);
4095
4097 newcre->resulttype = cre->resulttype;
4098 newcre->convertformat = cre->convertformat;
4099 newcre->location = cre->location;
4100
4101 /*
4102 * In case of a nested ConvertRowtypeExpr, we can convert the
4103 * leaf row directly to the topmost row format without any
4104 * intermediate conversions. (This works because
4105 * ConvertRowtypeExpr is used only for child->parent
4106 * conversion in inheritance trees, which works by exact match
4107 * of column name, and a column absent in an intermediate
4108 * result can't be present in the final result.)
4109 *
4110 * No need to check more than one level deep, because the
4111 * above recursion will have flattened anything else.
4112 */
4113 if (arg != NULL && IsA(arg, ConvertRowtypeExpr))
4114 {
4116
4117 arg = (Node *) argcre->arg;
4118
4119 /*
4120 * Make sure an outer implicit conversion can't hide an
4121 * inner explicit one.
4122 */
4123 if (newcre->convertformat == COERCE_IMPLICIT_CAST)
4124 newcre->convertformat = argcre->convertformat;
4125 }
4126
4127 newcre->arg = (Expr *) arg;
4128
4129 if (arg != NULL && IsA(arg, Const))
4130 return ece_evaluate_expr((Node *) newcre);
4131 return (Node *) newcre;
4132 }
4133 default:
4134 break;
4135 }
4136
4137 /*
4138 * For any node type not handled above, copy the node unchanged but
4139 * const-simplify its subexpressions. This is the correct thing for node
4140 * types whose behavior might change between planning and execution, such
4141 * as CurrentOfExpr. It's also a safe default for new node types not
4142 * known to this routine.
4143 */
4144 return ece_generic_processing(node);
4145}

References WindowFunc::aggfilter, AND_EXPR, applyRelabelType(), arg, CoerceViaIO::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, WindowFunc::args, FuncExpr::args, OpExpr::args, BoolExpr::args, RowExpr::args, Assert, BoolGetDatum(), BoolExpr::boolop, eval_const_expressions_context::boundParams, eval_const_expressions_context::case_val, castNode, check_stack_depth(), COERCE_IMPLICIT_CAST, CollateExpr::collOid, Const::consttype, contain_mutable_functions(), copyObject, datumCopy(), DatumGetBool(), DomainHasConstraints(), ece_all_arguments_const, ece_evaluate_expr, ece_function_is_safe(), ece_generic_processing, elog, ERROR, eval_const_expressions_context::estimate, eval_const_expressions_mutator(), evaluate_expr(), expand_function_arguments(), expr_is_nonnullable(), exprCollation(), expression_tree_mutator, exprType(), exprTypmod(), fb(), FuncExpr::funcid, get_typlenbyval(), getTypeInputInfo(), getTypeOutputInfo(), HeapTupleIsValid, WindowFunc::ignore_nulls, Int32GetDatum(), InvalidAttrNumber, InvalidOid, IS_FALSE, IS_NOT_FALSE, IS_NOT_NULL, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_NULL, IS_TRUE, IS_UNKNOWN, IsA, lappend(), lfirst, lfirst_node, linitial, list_length(), list_make1, list_make3, list_nth(), Param::location, WindowFunc::location, FuncExpr::location, OpExpr::location, CoerceViaIO::location, CollateExpr::location, lsecond, make_andclause(), make_notclause(), make_orclause(), makeBoolConst(), makeConst(), makeJsonValueExpr(), makeNode, makeNullConst(), makeVar(), memcpy(), negate_clause(), NIL, nodeTag, NOT_EXPR, NOTNULL_SOURCE_HASHTABLE, ParamListInfoData::numParams, ObjectIdGetDatum(), OidIsValid, OpExpr::opno, OR_EXPR, PARAM_EXTERN, PARAM_FLAG_CONST, Param::paramcollid, ParamListInfoData::paramFetch, Param::paramid, Param::paramkind, ParamListInfoData::params, Param::paramtype, Param::paramtypmod, record_plan_type_dependency(), ReleaseSysCache(), result, CoerceViaIO::resulttype, eval_const_expressions_context::root, rowtype_field_matches(), SearchSysCache1(), set_opfuncid(), set_sa_opfuncid(), simplify_aggref(), simplify_and_arguments(), simplify_boolean_equality(), simplify_function(), simplify_or_arguments(), SQLValueFunction::typmod, WindowFunc::winfnoid, and WindowFunc::winref.

Referenced by estimate_expression_value(), eval_const_expressions(), eval_const_expressions_mutator(), inline_function(), simplify_and_arguments(), simplify_function(), and simplify_or_arguments().

◆ evaluate_expr()

Expr * evaluate_expr ( Expr expr,
Oid  result_type,
int32  result_typmod,
Oid  result_collation 
)

Definition at line 5711 of file clauses.c.

5713{
5714 EState *estate;
5715 ExprState *exprstate;
5716 MemoryContext oldcontext;
5718 bool const_is_null;
5720 bool resultTypByVal;
5721
5722 /*
5723 * To use the executor, we need an EState.
5724 */
5725 estate = CreateExecutorState();
5726
5727 /* We can use the estate's working context to avoid memory leaks. */
5728 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
5729
5730 /* Make sure any opfuncids are filled in. */
5731 fix_opfuncids((Node *) expr);
5732
5733 /*
5734 * Prepare expr for execution. (Note: we can't use ExecPrepareExpr
5735 * because it'd result in recursively invoking eval_const_expressions.)
5736 */
5737 exprstate = ExecInitExpr(expr, NULL);
5738
5739 /*
5740 * And evaluate it.
5741 *
5742 * It is OK to use a default econtext because none of the ExecEvalExpr()
5743 * code used in this situation will use econtext. That might seem
5744 * fortuitous, but it's not so unreasonable --- a constant expression does
5745 * not depend on context, by definition, n'est ce pas?
5746 */
5748 GetPerTupleExprContext(estate),
5749 &const_is_null);
5750
5751 /* Get info needed about result datatype */
5753
5754 /* Get back to outer memory context */
5755 MemoryContextSwitchTo(oldcontext);
5756
5757 /*
5758 * Must copy result out of sub-context used by expression eval.
5759 *
5760 * Also, if it's varlena, forcibly detoast it. This protects us against
5761 * storing TOAST pointers into plans that might outlive the referenced
5762 * data. (makeConst would handle detoasting anyway, but it's worth a few
5763 * extra lines here so that we can do the copy and detoast in one step.)
5764 */
5765 if (!const_is_null)
5766 {
5767 if (resultTypLen == -1)
5769 else
5771 }
5772
5773 /* Release all the junk we just created */
5774 FreeExecutorState(estate);
5775
5776 /*
5777 * Make the constant result node.
5778 */
5779 return (Expr *) makeConst(result_type, result_typmod, result_collation,
5783}

References CreateExecutorState(), datumCopy(), EState::es_query_cxt, ExecEvalExprSwitchContext(), ExecInitExpr(), fb(), fix_opfuncids(), FreeExecutorState(), get_typlenbyval(), GetPerTupleExprContext, makeConst(), MemoryContextSwitchTo(), PG_DETOAST_DATUM_COPY, and PointerGetDatum.

Referenced by eval_const_expressions_mutator(), evaluate_function(), and transformPartitionBoundValue().

◆ evaluate_function()

static Expr * evaluate_function ( Oid  funcid,
Oid  result_type,
int32  result_typmod,
Oid  result_collid,
Oid  input_collid,
List args,
bool  funcvariadic,
HeapTuple  func_tuple,
eval_const_expressions_context context 
)
static

Definition at line 5164 of file clauses.c.

5169{
5171 bool has_nonconst_input = false;
5172 bool has_null_input = false;
5173 ListCell *arg;
5175
5176 /*
5177 * Can't simplify if it returns a set.
5178 */
5179 if (funcform->proretset)
5180 return NULL;
5181
5182 /*
5183 * Can't simplify if it returns RECORD. The immediate problem is that it
5184 * will be needing an expected tupdesc which we can't supply here.
5185 *
5186 * In the case where it has OUT parameters, we could build an expected
5187 * tupdesc from those, but there may be other gotchas lurking. In
5188 * particular, if the function were to return NULL, we would produce a
5189 * null constant with no remaining indication of which concrete record
5190 * type it is. For now, seems best to leave the function call unreduced.
5191 */
5192 if (funcform->prorettype == RECORDOID)
5193 return NULL;
5194
5195 /*
5196 * Check for constant inputs and especially constant-NULL inputs.
5197 */
5198 foreach(arg, args)
5199 {
5200 if (IsA(lfirst(arg), Const))
5202 else
5203 has_nonconst_input = true;
5204 }
5205
5206 /*
5207 * If the function is strict and has a constant-NULL input, it will never
5208 * be called at all, so we can replace the call by a NULL constant, even
5209 * if there are other inputs that aren't constant, and even if the
5210 * function is not otherwise immutable.
5211 */
5212 if (funcform->proisstrict && has_null_input)
5213 return (Expr *) makeNullConst(result_type, result_typmod,
5215
5216 /*
5217 * Otherwise, can simplify only if all inputs are constants. (For a
5218 * non-strict function, constant NULL inputs are treated the same as
5219 * constant non-NULL inputs.)
5220 */
5222 return NULL;
5223
5224 /*
5225 * Ordinarily we are only allowed to simplify immutable functions. But for
5226 * purposes of estimation, we consider it okay to simplify functions that
5227 * are merely stable; the risk that the result might change from planning
5228 * time to execution time is worth taking in preference to not being able
5229 * to estimate the value at all.
5230 */
5231 if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
5232 /* okay */ ;
5233 else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
5234 /* okay */ ;
5235 else
5236 return NULL;
5237
5238 /*
5239 * OK, looks like we can simplify this operator/function.
5240 *
5241 * Build a new FuncExpr node containing the already-simplified arguments.
5242 */
5244 newexpr->funcid = funcid;
5245 newexpr->funcresulttype = result_type;
5246 newexpr->funcretset = false;
5247 newexpr->funcvariadic = funcvariadic;
5248 newexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
5249 newexpr->funccollid = result_collid; /* doesn't matter */
5250 newexpr->inputcollid = input_collid;
5251 newexpr->args = args;
5252 newexpr->location = -1;
5253
5254 return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
5256}

References arg, COERCE_EXPLICIT_CALL, eval_const_expressions_context::estimate, evaluate_expr(), fb(), Form_pg_proc, GETSTRUCT(), IsA, lfirst, makeNode, and makeNullConst().

Referenced by simplify_function().

◆ expand_function_arguments()

List * expand_function_arguments ( List args,
bool  include_out_arguments,
Oid  result_type,
HeapTuple  func_tuple 
)

Definition at line 4914 of file clauses.c.

4916{
4918 Oid *proargtypes = funcform->proargtypes.values;
4919 int pronargs = funcform->pronargs;
4920 bool has_named_args = false;
4921 ListCell *lc;
4922
4923 /*
4924 * If we are asked to match to OUT arguments, then use the proallargtypes
4925 * array (which includes those); otherwise use proargtypes (which
4926 * doesn't). Of course, if proallargtypes is null, we always use
4927 * proargtypes. (Fetching proallargtypes is annoyingly expensive
4928 * considering that we may have nothing to do here, but fortunately the
4929 * common case is include_out_arguments == false.)
4930 */
4932 {
4934 bool isNull;
4935
4938 &isNull);
4939 if (!isNull)
4940 {
4942
4943 pronargs = ARR_DIMS(arr)[0];
4944 if (ARR_NDIM(arr) != 1 ||
4945 pronargs < 0 ||
4946 ARR_HASNULL(arr) ||
4947 ARR_ELEMTYPE(arr) != OIDOID)
4948 elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
4949 Assert(pronargs >= funcform->pronargs);
4950 proargtypes = (Oid *) ARR_DATA_PTR(arr);
4951 }
4952 }
4953
4954 /* Do we have any named arguments? */
4955 foreach(lc, args)
4956 {
4957 Node *arg = (Node *) lfirst(lc);
4958
4959 if (IsA(arg, NamedArgExpr))
4960 {
4961 has_named_args = true;
4962 break;
4963 }
4964 }
4965
4966 /* If so, we must apply reorder_function_arguments */
4967 if (has_named_args)
4968 {
4970 /* Recheck argument types and add casts if needed */
4971 recheck_cast_function_args(args, result_type,
4973 func_tuple);
4974 }
4975 else if (list_length(args) < pronargs)
4976 {
4977 /* No named args, but we seem to be short some defaults */
4979 /* Recheck argument types and add casts if needed */
4980 recheck_cast_function_args(args, result_type,
4982 func_tuple);
4983 }
4984
4985 return args;
4986}

References add_function_defaults(), arg, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, Assert, DatumGetArrayTypeP, elog, ERROR, fb(), Form_pg_proc, GETSTRUCT(), IsA, lfirst, list_length(), pronargs, recheck_cast_function_args(), reorder_function_arguments(), and SysCacheGetAttr().

Referenced by eval_const_expressions_mutator(), simplify_function(), and transformCallStmt().

◆ expr_is_nonnullable()

bool expr_is_nonnullable ( PlannerInfo root,
Expr expr,
NotNullSource  source 
)

Definition at line 4772 of file clauses.c.

4773{
4774 /* since this function recurses, it could be driven to stack overflow */
4776
4777 switch (nodeTag(expr))
4778 {
4779 case T_Var:
4780 {
4781 if (root)
4782 return var_is_nonnullable(root, (Var *) expr, source);
4783 }
4784 break;
4785 case T_Const:
4786 return !((Const *) expr)->constisnull;
4787 case T_CoalesceExpr:
4788 {
4789 /*
4790 * A CoalesceExpr returns NULL if and only if all its
4791 * arguments are NULL. Therefore, we can determine that a
4792 * CoalesceExpr cannot be NULL if at least one of its
4793 * arguments can be proven non-nullable.
4794 */
4796
4798 {
4800 return true;
4801 }
4802 }
4803 break;
4804 case T_MinMaxExpr:
4805 {
4806 /*
4807 * Like CoalesceExpr, a MinMaxExpr returns NULL only if all
4808 * its arguments evaluate to NULL.
4809 */
4810 MinMaxExpr *minmaxexpr = (MinMaxExpr *) expr;
4811
4813 {
4815 return true;
4816 }
4817 }
4818 break;
4819 case T_CaseExpr:
4820 {
4821 /*
4822 * A CASE expression is non-nullable if all branch results are
4823 * non-nullable. We must also verify that the default result
4824 * (ELSE) exists and is non-nullable.
4825 */
4826 CaseExpr *caseexpr = (CaseExpr *) expr;
4827
4828 /* The default result must be present and non-nullable */
4829 if (caseexpr->defresult == NULL ||
4830 !expr_is_nonnullable(root, caseexpr->defresult, source))
4831 return false;
4832
4833 /* All branch results must be non-nullable */
4835 {
4836 if (!expr_is_nonnullable(root, casewhen->result, source))
4837 return false;
4838 }
4839
4840 return true;
4841 }
4842 break;
4843 case T_ArrayExpr:
4844 {
4845 /*
4846 * An ARRAY[] expression always returns a valid Array object,
4847 * even if it is empty (ARRAY[]) or contains NULLs
4848 * (ARRAY[NULL]). It never evaluates to a SQL NULL.
4849 */
4850 return true;
4851 }
4852 case T_NullTest:
4853 {
4854 /*
4855 * An IS NULL / IS NOT NULL expression always returns a
4856 * boolean value. It never returns SQL NULL.
4857 */
4858 return true;
4859 }
4860 case T_BooleanTest:
4861 {
4862 /*
4863 * A BooleanTest expression always evaluates to a boolean
4864 * value. It never returns SQL NULL.
4865 */
4866 return true;
4867 }
4868 case T_DistinctExpr:
4869 {
4870 /*
4871 * IS DISTINCT FROM never returns NULL, effectively acting as
4872 * though NULL were a normal data value.
4873 */
4874 return true;
4875 }
4876 case T_RelabelType:
4877 {
4878 /*
4879 * RelabelType does not change the nullability of the data.
4880 * The result is non-nullable if and only if the argument is
4881 * non-nullable.
4882 */
4883 return expr_is_nonnullable(root, ((RelabelType *) expr)->arg,
4884 source);
4885 }
4886 default:
4887 break;
4888 }
4889
4890 return false;
4891}

References arg, check_stack_depth(), expr_is_nonnullable(), fb(), foreach_ptr, nodeTag, root, source, and var_is_nonnullable().

Referenced by eval_const_expressions_mutator(), expr_is_nonnullable(), int8inc_support(), query_outputs_are_not_nullable(), restriction_is_always_false(), restriction_is_always_true(), and sublink_testexpr_is_not_nullable().

◆ expression_returns_set_rows()

double expression_returns_set_rows ( PlannerInfo root,
Node clause 
)

Definition at line 302 of file clauses.c.

303{
304 if (clause == NULL)
305 return 1.0;
306 if (IsA(clause, FuncExpr))
307 {
308 FuncExpr *expr = (FuncExpr *) clause;
309
310 if (expr->funcretset)
311 return clamp_row_est(get_function_rows(root, expr->funcid, clause));
312 }
313 if (IsA(clause, OpExpr))
314 {
315 OpExpr *expr = (OpExpr *) clause;
316
317 if (expr->opretset)
318 {
319 set_opfuncid(expr);
320 return clamp_row_est(get_function_rows(root, expr->opfuncid, clause));
321 }
322 }
323 return 1.0;
324}
double clamp_row_est(double nrows)
Definition costsize.c:214
double get_function_rows(PlannerInfo *root, Oid funcid, Node *node)
Definition plancat.c:2419

References clamp_row_est(), fb(), FuncExpr::funcid, get_function_rows(), IsA, root, and set_opfuncid().

Referenced by create_set_projection_path(), estimate_num_groups(), and set_function_size_estimates().

◆ fetch_function_defaults()

static List * fetch_function_defaults ( HeapTuple  func_tuple)
static

Definition at line 5089 of file clauses.c.

5090{
5091 List *defaults;
5093 char *str;
5094
5098 defaults = castNode(List, stringToNode(str));
5099 pfree(str);
5100 return defaults;
5101}

References castNode, fb(), pfree(), str, stringToNode(), SysCacheGetAttrNotNull(), and TextDatumGetCString.

Referenced by add_function_defaults(), and reorder_function_arguments().

◆ find_forced_null_var()

Var * find_forced_null_var ( Node node)

Definition at line 1997 of file clauses.c.

1998{
1999 if (node == NULL)
2000 return NULL;
2001 if (IsA(node, NullTest))
2002 {
2003 /* check for var IS NULL */
2004 NullTest *expr = (NullTest *) node;
2005
2006 if (expr->nulltesttype == IS_NULL && !expr->argisrow)
2007 {
2008 Var *var = (Var *) expr->arg;
2009
2010 if (var && IsA(var, Var) &&
2011 var->varlevelsup == 0)
2012 return var;
2013 }
2014 }
2015 else if (IsA(node, BooleanTest))
2016 {
2017 /* var IS UNKNOWN is equivalent to var IS NULL */
2018 BooleanTest *expr = (BooleanTest *) node;
2019
2020 if (expr->booltesttype == IS_UNKNOWN)
2021 {
2022 Var *var = (Var *) expr->arg;
2023
2024 if (var && IsA(var, Var) &&
2025 var->varlevelsup == 0)
2026 return var;
2027 }
2028 }
2029 return NULL;
2030}
BoolTestType booltesttype
Definition primnodes.h:2011
NullTestType nulltesttype
Definition primnodes.h:1987
Expr * arg
Definition primnodes.h:1986

References NullTest::arg, BooleanTest::arg, BooleanTest::booltesttype, fb(), IS_NULL, IS_UNKNOWN, IsA, NullTest::nulltesttype, and Var::varlevelsup.

Referenced by check_redundant_nullability_qual(), and find_forced_null_vars().

◆ find_forced_null_vars()

List * find_forced_null_vars ( Node node)

Definition at line 1936 of file clauses.c.

1937{
1938 List *result = NIL;
1939 Var *var;
1940 ListCell *l;
1941
1942 if (node == NULL)
1943 return NIL;
1944 /* Check single-clause cases using subroutine */
1945 var = find_forced_null_var(node);
1946 if (var)
1947 {
1949 var->varno,
1951 }
1952 /* Otherwise, handle AND-conditions */
1953 else if (IsA(node, List))
1954 {
1955 /*
1956 * At top level, we are examining an implicit-AND list: if any of the
1957 * arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1958 */
1959 foreach(l, (List *) node)
1960 {
1963 }
1964 }
1965 else if (IsA(node, BoolExpr))
1966 {
1967 BoolExpr *expr = (BoolExpr *) node;
1968
1969 /*
1970 * We don't bother considering the OR case, because it's fairly
1971 * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
1972 * the NOT case isn't worth expending code on.
1973 */
1974 if (expr->boolop == AND_EXPR)
1975 {
1976 /* At top level we can just recurse (to the List case) */
1978 }
1979 }
1980 return result;
1981}
List * find_forced_null_vars(Node *node)
Definition clauses.c:1936
Var * find_forced_null_var(Node *node)
Definition clauses.c:1997
List * mbms_add_members(List *a, const List *b)
List * mbms_add_member(List *a, int listidx, int bitidx)
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27

References AND_EXPR, BoolExpr::args, BoolExpr::boolop, fb(), find_forced_null_var(), find_forced_null_vars(), FirstLowInvalidHeapAttributeNumber, IsA, lfirst, mbms_add_member(), mbms_add_members(), NIL, result, Var::varattno, and Var::varno.

Referenced by find_forced_null_vars(), and reduce_outer_joins_pass2().

◆ find_nonnullable_rels()

Relids find_nonnullable_rels ( Node clause)

Definition at line 1476 of file clauses.c.

1477{
1478 return find_nonnullable_rels_walker(clause, true);
1479}
static Relids find_nonnullable_rels_walker(Node *node, bool top_level)
Definition clauses.c:1482

References find_nonnullable_rels_walker().

Referenced by make_outerjoininfo(), and reduce_outer_joins_pass2().

◆ find_nonnullable_rels_walker()

static Relids find_nonnullable_rels_walker ( Node node,
bool  top_level 
)
static

Definition at line 1482 of file clauses.c.

1483{
1484 Relids result = NULL;
1485 ListCell *l;
1486
1487 if (node == NULL)
1488 return NULL;
1489 if (IsA(node, Var))
1490 {
1491 Var *var = (Var *) node;
1492
1493 if (var->varlevelsup == 0)
1495 }
1496 else if (IsA(node, List))
1497 {
1498 /*
1499 * At top level, we are examining an implicit-AND list: if any of the
1500 * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1501 * not at top level, we are examining the arguments of a strict
1502 * function: if any of them produce NULL then the result of the
1503 * function must be NULL. So in both cases, the set of nonnullable
1504 * rels is the union of those found in the arms, and we pass down the
1505 * top_level flag unmodified.
1506 */
1507 foreach(l, (List *) node)
1508 {
1511 top_level));
1512 }
1513 }
1514 else if (IsA(node, FuncExpr))
1515 {
1516 FuncExpr *expr = (FuncExpr *) node;
1517
1518 if (func_strict(expr->funcid))
1519 result = find_nonnullable_rels_walker((Node *) expr->args, false);
1520 }
1521 else if (IsA(node, OpExpr))
1522 {
1523 OpExpr *expr = (OpExpr *) node;
1524
1525 set_opfuncid(expr);
1526 if (func_strict(expr->opfuncid))
1527 result = find_nonnullable_rels_walker((Node *) expr->args, false);
1528 }
1529 else if (IsA(node, ScalarArrayOpExpr))
1530 {
1531 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1532
1533 if (is_strict_saop(expr, true))
1534 result = find_nonnullable_rels_walker((Node *) expr->args, false);
1535 }
1536 else if (IsA(node, BoolExpr))
1537 {
1538 BoolExpr *expr = (BoolExpr *) node;
1539
1540 switch (expr->boolop)
1541 {
1542 case AND_EXPR:
1543 /* At top level we can just recurse (to the List case) */
1544 if (top_level)
1545 {
1547 top_level);
1548 break;
1549 }
1550
1551 /*
1552 * Below top level, even if one arm produces NULL, the result
1553 * could be FALSE (hence not NULL). However, if *all* the
1554 * arms produce NULL then the result is NULL, so we can take
1555 * the intersection of the sets of nonnullable rels, just as
1556 * for OR. Fall through to share code.
1557 */
1559 case OR_EXPR:
1560
1561 /*
1562 * OR is strict if all of its arms are, so we can take the
1563 * intersection of the sets of nonnullable rels for each arm.
1564 * This works for both values of top_level.
1565 */
1566 foreach(l, expr->args)
1567 {
1569
1571 top_level);
1572 if (result == NULL) /* first subresult? */
1573 result = subresult;
1574 else
1576
1577 /*
1578 * If the intersection is empty, we can stop looking. This
1579 * also justifies the test for first-subresult above.
1580 */
1581 if (bms_is_empty(result))
1582 break;
1583 }
1584 break;
1585 case NOT_EXPR:
1586 /* NOT will return null if its arg is null */
1588 false);
1589 break;
1590 default:
1591 elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1592 break;
1593 }
1594 }
1595 else if (IsA(node, RelabelType))
1596 {
1597 RelabelType *expr = (RelabelType *) node;
1598
1599 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1600 }
1601 else if (IsA(node, CoerceViaIO))
1602 {
1603 /* not clear this is useful, but it can't hurt */
1604 CoerceViaIO *expr = (CoerceViaIO *) node;
1605
1606 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1607 }
1608 else if (IsA(node, ArrayCoerceExpr))
1609 {
1610 /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1611 ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1612
1613 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1614 }
1615 else if (IsA(node, ConvertRowtypeExpr))
1616 {
1617 /* not clear this is useful, but it can't hurt */
1618 ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1619
1620 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1621 }
1622 else if (IsA(node, CollateExpr))
1623 {
1624 CollateExpr *expr = (CollateExpr *) node;
1625
1626 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
1627 }
1628 else if (IsA(node, NullTest))
1629 {
1630 /* IS NOT NULL can be considered strict, but only at top level */
1631 NullTest *expr = (NullTest *) node;
1632
1633 if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1634 result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1635 }
1636 else if (IsA(node, BooleanTest))
1637 {
1638 /* Boolean tests that reject NULL are strict at top level */
1639 BooleanTest *expr = (BooleanTest *) node;
1640
1641 if (top_level &&
1642 (expr->booltesttype == IS_TRUE ||
1643 expr->booltesttype == IS_FALSE ||
1644 expr->booltesttype == IS_NOT_UNKNOWN))
1645 result = find_nonnullable_rels_walker((Node *) expr->arg, false);
1646 }
1647 else if (IsA(node, SubPlan))
1648 {
1649 SubPlan *splan = (SubPlan *) node;
1650
1651 /*
1652 * For some types of SubPlan, we can infer strictness from Vars in the
1653 * testexpr (the LHS of the original SubLink).
1654 *
1655 * For ANY_SUBLINK, if the subquery produces zero rows, the result is
1656 * always FALSE. If the subquery produces more than one row, the
1657 * per-row results of the testexpr are combined using OR semantics.
1658 * Hence ANY_SUBLINK can be strict only at top level, but there it's
1659 * as strict as the testexpr is.
1660 *
1661 * For ROWCOMPARE_SUBLINK, if the subquery produces zero rows, the
1662 * result is always NULL. Otherwise, the result is as strict as the
1663 * testexpr is. So we can check regardless of top_level.
1664 *
1665 * We can't prove anything for other sublink types (in particular,
1666 * note that ALL_SUBLINK will return TRUE if the subquery is empty).
1667 */
1668 if ((top_level && splan->subLinkType == ANY_SUBLINK) ||
1670 result = find_nonnullable_rels_walker(splan->testexpr, top_level);
1671 }
1672 else if (IsA(node, PlaceHolderVar))
1673 {
1674 PlaceHolderVar *phv = (PlaceHolderVar *) node;
1675
1676 /*
1677 * If the contained expression forces any rels non-nullable, so does
1678 * the PHV.
1679 */
1680 result = find_nonnullable_rels_walker((Node *) phv->phexpr, top_level);
1681
1682 /*
1683 * If the PHV's syntactic scope is exactly one rel, it will be forced
1684 * to be evaluated at that rel, and so it will behave like a Var of
1685 * that rel: if the rel's entire output goes to null, so will the PHV.
1686 * (If the syntactic scope is a join, we know that the PHV will go to
1687 * null if the whole join does; but that is AND semantics while we
1688 * need OR semantics for find_nonnullable_rels' result, so we can't do
1689 * anything with the knowledge.)
1690 */
1691 if (phv->phlevelsup == 0 &&
1692 bms_membership(phv->phrels) == BMS_SINGLETON)
1693 result = bms_add_members(result, phv->phrels);
1694 }
1695 return result;
1696}
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:216
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1093
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:901
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:765
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition bitmapset.c:1214
@ BMS_SINGLETON
Definition bitmapset.h:72
#define pg_fallthrough
Definition c.h:161
static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
Definition clauses.c:2271
@ ANY_SUBLINK
Definition primnodes.h:1032
@ ROWCOMPARE_SUBLINK
Definition primnodes.h:1033
Node * testexpr
Definition primnodes.h:1100
SubLinkType subLinkType
Definition primnodes.h:1098

References AND_EXPR, ANY_SUBLINK, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, NullTest::arg, BooleanTest::arg, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, bms_add_members(), bms_int_members(), bms_is_empty, bms_join(), bms_make_singleton(), bms_membership(), BMS_SINGLETON, BoolExpr::boolop, BooleanTest::booltesttype, elog, ERROR, fb(), find_nonnullable_rels_walker(), func_strict(), FuncExpr::funcid, IS_FALSE, IS_NOT_NULL, IS_NOT_UNKNOWN, is_strict_saop(), IS_TRUE, IsA, lfirst, NOT_EXPR, NullTest::nulltesttype, OR_EXPR, pg_fallthrough, result, ROWCOMPARE_SUBLINK, set_opfuncid(), SubPlan::subLinkType, SubPlan::testexpr, Var::varlevelsup, and Var::varno.

Referenced by find_nonnullable_rels(), and find_nonnullable_rels_walker().

◆ find_nonnullable_vars()

List * find_nonnullable_vars ( Node clause)

Definition at line 1727 of file clauses.c.

1728{
1729 return find_nonnullable_vars_walker(clause, true);
1730}
static List * find_nonnullable_vars_walker(Node *node, bool top_level)
Definition clauses.c:1733

References find_nonnullable_vars_walker().

Referenced by query_outputs_are_not_nullable(), and reduce_outer_joins_pass2().

◆ find_nonnullable_vars_walker()

static List * find_nonnullable_vars_walker ( Node node,
bool  top_level 
)
static

Definition at line 1733 of file clauses.c.

1734{
1735 List *result = NIL;
1736 ListCell *l;
1737
1738 if (node == NULL)
1739 return NIL;
1740 if (IsA(node, Var))
1741 {
1742 Var *var = (Var *) node;
1743
1744 if (var->varlevelsup == 0)
1746 var->varno,
1748 }
1749 else if (IsA(node, List))
1750 {
1751 /*
1752 * At top level, we are examining an implicit-AND list: if any of the
1753 * arms produces FALSE-or-NULL then the result is FALSE-or-NULL. If
1754 * not at top level, we are examining the arguments of a strict
1755 * function: if any of them produce NULL then the result of the
1756 * function must be NULL. So in both cases, the set of nonnullable
1757 * vars is the union of those found in the arms, and we pass down the
1758 * top_level flag unmodified.
1759 */
1760 foreach(l, (List *) node)
1761 {
1764 top_level));
1765 }
1766 }
1767 else if (IsA(node, FuncExpr))
1768 {
1769 FuncExpr *expr = (FuncExpr *) node;
1770
1771 if (func_strict(expr->funcid))
1772 result = find_nonnullable_vars_walker((Node *) expr->args, false);
1773 }
1774 else if (IsA(node, OpExpr))
1775 {
1776 OpExpr *expr = (OpExpr *) node;
1777
1778 set_opfuncid(expr);
1779 if (func_strict(expr->opfuncid))
1780 result = find_nonnullable_vars_walker((Node *) expr->args, false);
1781 }
1782 else if (IsA(node, ScalarArrayOpExpr))
1783 {
1784 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
1785
1786 if (is_strict_saop(expr, true))
1787 result = find_nonnullable_vars_walker((Node *) expr->args, false);
1788 }
1789 else if (IsA(node, BoolExpr))
1790 {
1791 BoolExpr *expr = (BoolExpr *) node;
1792
1793 switch (expr->boolop)
1794 {
1795 case AND_EXPR:
1796
1797 /*
1798 * At top level we can just recurse (to the List case), since
1799 * the result should be the union of what we can prove in each
1800 * arm.
1801 */
1802 if (top_level)
1803 {
1805 top_level);
1806 break;
1807 }
1808
1809 /*
1810 * Below top level, even if one arm produces NULL, the result
1811 * could be FALSE (hence not NULL). However, if *all* the
1812 * arms produce NULL then the result is NULL, so we can take
1813 * the intersection of the sets of nonnullable vars, just as
1814 * for OR. Fall through to share code.
1815 */
1817 case OR_EXPR:
1818
1819 /*
1820 * OR is strict if all of its arms are, so we can take the
1821 * intersection of the sets of nonnullable vars for each arm.
1822 * This works for both values of top_level.
1823 */
1824 foreach(l, expr->args)
1825 {
1826 List *subresult;
1827
1829 top_level);
1830 if (result == NIL) /* first subresult? */
1831 result = subresult;
1832 else
1834
1835 /*
1836 * If the intersection is empty, we can stop looking. This
1837 * also justifies the test for first-subresult above.
1838 */
1839 if (result == NIL)
1840 break;
1841 }
1842 break;
1843 case NOT_EXPR:
1844 /* NOT will return null if its arg is null */
1846 false);
1847 break;
1848 default:
1849 elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
1850 break;
1851 }
1852 }
1853 else if (IsA(node, RelabelType))
1854 {
1855 RelabelType *expr = (RelabelType *) node;
1856
1857 result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1858 }
1859 else if (IsA(node, CoerceViaIO))
1860 {
1861 /* not clear this is useful, but it can't hurt */
1862 CoerceViaIO *expr = (CoerceViaIO *) node;
1863
1864 result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1865 }
1866 else if (IsA(node, ArrayCoerceExpr))
1867 {
1868 /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
1869 ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
1870
1871 result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1872 }
1873 else if (IsA(node, ConvertRowtypeExpr))
1874 {
1875 /* not clear this is useful, but it can't hurt */
1876 ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
1877
1878 result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1879 }
1880 else if (IsA(node, CollateExpr))
1881 {
1882 CollateExpr *expr = (CollateExpr *) node;
1883
1884 result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
1885 }
1886 else if (IsA(node, NullTest))
1887 {
1888 /* IS NOT NULL can be considered strict, but only at top level */
1889 NullTest *expr = (NullTest *) node;
1890
1891 if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
1892 result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1893 }
1894 else if (IsA(node, BooleanTest))
1895 {
1896 /* Boolean tests that reject NULL are strict at top level */
1897 BooleanTest *expr = (BooleanTest *) node;
1898
1899 if (top_level &&
1900 (expr->booltesttype == IS_TRUE ||
1901 expr->booltesttype == IS_FALSE ||
1902 expr->booltesttype == IS_NOT_UNKNOWN))
1903 result = find_nonnullable_vars_walker((Node *) expr->arg, false);
1904 }
1905 else if (IsA(node, SubPlan))
1906 {
1907 SubPlan *splan = (SubPlan *) node;
1908
1909 /* See analysis in find_nonnullable_rels_walker */
1910 if ((top_level && splan->subLinkType == ANY_SUBLINK) ||
1912 result = find_nonnullable_vars_walker(splan->testexpr, top_level);
1913 }
1914 else if (IsA(node, PlaceHolderVar))
1915 {
1916 PlaceHolderVar *phv = (PlaceHolderVar *) node;
1917
1918 result = find_nonnullable_vars_walker((Node *) phv->phexpr, top_level);
1919 }
1920 return result;
1921}
List * mbms_int_members(List *a, const List *b)

References AND_EXPR, ANY_SUBLINK, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, NullTest::arg, BooleanTest::arg, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, elog, ERROR, fb(), find_nonnullable_vars_walker(), FirstLowInvalidHeapAttributeNumber, func_strict(), FuncExpr::funcid, IS_FALSE, IS_NOT_NULL, IS_NOT_UNKNOWN, is_strict_saop(), IS_TRUE, IsA, lfirst, mbms_add_member(), mbms_add_members(), mbms_int_members(), NIL, NOT_EXPR, NullTest::nulltesttype, OR_EXPR, pg_fallthrough, result, ROWCOMPARE_SUBLINK, set_opfuncid(), SubPlan::subLinkType, SubPlan::testexpr, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by find_nonnullable_vars(), and find_nonnullable_vars_walker().

◆ find_subquery_safe_quals()

static void find_subquery_safe_quals ( Node jtnode,
List **  safe_quals 
)
static

Definition at line 2189 of file clauses.c.

2190{
2191 if (jtnode == NULL)
2192 return;
2193 if (IsA(jtnode, RangeTblRef))
2194 {
2195 /* Leaf node: nothing to do */
2196 return;
2197 }
2198 else if (IsA(jtnode, FromExpr))
2199 {
2200 FromExpr *f = (FromExpr *) jtnode;
2201
2202 /* All elements of the FROM list are allowable */
2205 /* ... and its WHERE quals are too */
2206 if (f->quals)
2207 *safe_quals = lappend(*safe_quals, f->quals);
2208 }
2209 else if (IsA(jtnode, JoinExpr))
2210 {
2211 JoinExpr *j = (JoinExpr *) jtnode;
2212
2213 switch (j->jointype)
2214 {
2215 case JOIN_INNER:
2216 /* visit both children */
2219 /* and grab the ON quals too */
2220 if (j->quals)
2221 *safe_quals = lappend(*safe_quals, j->quals);
2222 break;
2223
2224 case JOIN_LEFT:
2225 case JOIN_SEMI:
2226 case JOIN_ANTI:
2227
2228 /*
2229 * Only the left input is possibly non-nullable; furthermore,
2230 * the quals of this join don't constrain the left input.
2231 * Note: we probably can't see SEMI or ANTI joins at this
2232 * point, but if we do, we can treat them like LEFT joins.
2233 */
2235 break;
2236
2237 case JOIN_RIGHT:
2238 /* Reverse of the above case */
2240 break;
2241
2242 case JOIN_FULL:
2243 /* Neither side is non-nullable, so stop descending */
2244 break;
2245
2246 default:
2247 elog(ERROR, "unrecognized join type: %d",
2248 (int) j->jointype);
2249 break;
2250 }
2251 }
2252 else
2253 elog(ERROR, "unrecognized node type: %d",
2254 (int) nodeTag(jtnode));
2255}
static void find_subquery_safe_quals(Node *jtnode, List **safe_quals)
Definition clauses.c:2189
if(enc< 0)
int j
Definition isn.c:78
@ JOIN_SEMI
Definition nodes.h:317
@ JOIN_FULL
Definition nodes.h:305
@ JOIN_INNER
Definition nodes.h:303
@ JOIN_RIGHT
Definition nodes.h:306
@ JOIN_LEFT
Definition nodes.h:304
@ JOIN_ANTI
Definition nodes.h:318
List * fromlist
Definition primnodes.h:2384

References elog, ERROR, fb(), find_subquery_safe_quals(), foreach_ptr, FromExpr::fromlist, IsA, j, JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_RIGHT, JOIN_SEMI, lappend(), nodeTag, and FromExpr::quals.

Referenced by find_subquery_safe_quals(), and query_outputs_are_not_nullable().

◆ find_window_functions()

WindowFuncLists * find_window_functions ( Node clause,
Index  maxWinRef 
)

Definition at line 244 of file clauses.c.

245{
247
248 lists->numWindowFuncs = 0;
249 lists->maxWinRef = maxWinRef;
250 lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
252 return lists;
253}
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists)
Definition clauses.c:256
#define palloc_object(type)
Definition fe_memutils.h:74

References fb(), find_window_functions_walker(), palloc0(), and palloc_object.

Referenced by grouping_planner().

◆ find_window_functions_walker()

static bool find_window_functions_walker ( Node node,
WindowFuncLists lists 
)
static

Definition at line 256 of file clauses.c.

257{
258 if (node == NULL)
259 return false;
260 if (IsA(node, WindowFunc))
261 {
262 WindowFunc *wfunc = (WindowFunc *) node;
263
264 /* winref is unsigned, so one-sided test is OK */
265 if (wfunc->winref > lists->maxWinRef)
266 elog(ERROR, "WindowFunc contains out-of-range winref %u",
267 wfunc->winref);
268
269 lists->windowFuncs[wfunc->winref] =
270 lappend(lists->windowFuncs[wfunc->winref], wfunc);
271 lists->numWindowFuncs++;
272
273 /*
274 * We assume that the parser checked that there are no window
275 * functions in the arguments or filter clause. Hence, we need not
276 * recurse into them. (If either the parser or the planner screws up
277 * on this point, the executor will still catch it; see ExecInitExpr.)
278 */
279 return false;
280 }
281 Assert(!IsA(node, SubLink));
283}

References Assert, elog, ERROR, expression_tree_walker, fb(), find_window_functions_walker(), IsA, lappend(), and WindowFunc::winref.

Referenced by find_window_functions(), and find_window_functions_walker().

◆ inline_function()

static Expr * inline_function ( Oid  funcid,
Oid  result_type,
Oid  result_collid,
Oid  input_collid,
List args,
bool  funcvariadic,
HeapTuple  func_tuple,
eval_const_expressions_context context 
)
static

Definition at line 5290 of file clauses.c.

5295{
5297 char *src;
5298 Datum tmp;
5299 bool isNull;
5302 inline_error_callback_arg callback_arg;
5304 FuncExpr *fexpr;
5306 TupleDesc rettupdesc;
5307 ParseState *pstate;
5311 Node *newexpr;
5312 int *usecounts;
5313 ListCell *arg;
5314 int i;
5315
5316 /*
5317 * Forget it if the function is not SQL-language or has other showstopper
5318 * properties. (The prokind and nargs checks are just paranoia.)
5319 */
5320 if (funcform->prolang != SQLlanguageId ||
5321 funcform->prokind != PROKIND_FUNCTION ||
5322 funcform->prosecdef ||
5323 funcform->proretset ||
5324 funcform->prorettype == RECORDOID ||
5326 funcform->pronargs != list_length(args))
5327 return NULL;
5328
5329 /* Check for recursive function, and give up trying to expand if so */
5330 if (list_member_oid(context->active_fns, funcid))
5331 return NULL;
5332
5333 /* Check permission to call function (fail later, if not) */
5335 return NULL;
5336
5337 /* Check whether a plugin wants to hook function entry/exit */
5338 if (FmgrHookIsNeeded(funcid))
5339 return NULL;
5340
5341 /*
5342 * Make a temporary memory context, so that we don't leak all the stuff
5343 * that parsing might create.
5344 */
5346 "inline_function",
5349
5350 /*
5351 * We need a dummy FuncExpr node containing the already-simplified
5352 * arguments. (In some cases we don't really need it, but building it is
5353 * cheap enough that it's not worth contortions to avoid.)
5354 */
5356 fexpr->funcid = funcid;
5357 fexpr->funcresulttype = result_type;
5358 fexpr->funcretset = false;
5359 fexpr->funcvariadic = funcvariadic;
5360 fexpr->funcformat = COERCE_EXPLICIT_CALL; /* doesn't matter */
5361 fexpr->funccollid = result_collid; /* doesn't matter */
5362 fexpr->inputcollid = input_collid;
5363 fexpr->args = args;
5364 fexpr->location = -1;
5365
5366 /* Fetch the function body */
5368 src = TextDatumGetCString(tmp);
5369
5370 /*
5371 * Setup error traceback support for ereport(). This is so that we can
5372 * finger the function that bad information came from.
5373 */
5374 callback_arg.proname = NameStr(funcform->proname);
5375 callback_arg.prosrc = src;
5376
5378 sqlerrcontext.arg = &callback_arg;
5381
5382 /* If we have prosqlbody, pay attention to that not prosrc */
5384 func_tuple,
5386 &isNull);
5387 if (!isNull)
5388 {
5389 Node *n;
5390 List *query_list;
5391
5393 if (IsA(n, List))
5394 query_list = linitial_node(List, castNode(List, n));
5395 else
5396 query_list = list_make1(n);
5397 if (list_length(query_list) != 1)
5398 goto fail;
5399 querytree = linitial(query_list);
5400
5401 /*
5402 * Because we'll insist below that the querytree have an empty rtable
5403 * and no sublinks, it cannot have any relation references that need
5404 * to be locked or rewritten. So we can omit those steps.
5405 */
5406 }
5407 else
5408 {
5409 /* Set up to handle parameters while parsing the function body. */
5411 (Node *) fexpr,
5412 input_collid);
5413
5414 /*
5415 * We just do parsing and parse analysis, not rewriting, because
5416 * rewriting will not affect table-free-SELECT-only queries, which is
5417 * all that we care about. Also, we can punt as soon as we detect
5418 * more than one command in the function body.
5419 */
5422 goto fail;
5423
5424 pstate = make_parsestate(NULL);
5425 pstate->p_sourcetext = src;
5426 sql_fn_parser_setup(pstate, pinfo);
5427
5429
5430 free_parsestate(pstate);
5431 }
5432
5433 /*
5434 * The single command must be a simple "SELECT expression".
5435 *
5436 * Note: if you change the tests involved in this, see also plpgsql's
5437 * exec_simple_check_plan(). That generally needs to have the same idea
5438 * of what's a "simple expression", so that inlining a function that
5439 * previously wasn't inlined won't change plpgsql's conclusion.
5440 */
5441 if (!IsA(querytree, Query) ||
5442 querytree->commandType != CMD_SELECT ||
5443 querytree->hasAggs ||
5444 querytree->hasWindowFuncs ||
5445 querytree->hasTargetSRFs ||
5446 querytree->hasSubLinks ||
5447 querytree->cteList ||
5448 querytree->rtable ||
5449 querytree->jointree->fromlist ||
5450 querytree->jointree->quals ||
5451 querytree->groupClause ||
5452 querytree->groupingSets ||
5453 querytree->havingQual ||
5454 querytree->windowClause ||
5455 querytree->distinctClause ||
5456 querytree->sortClause ||
5457 querytree->limitOffset ||
5458 querytree->limitCount ||
5459 querytree->setOperations ||
5460 list_length(querytree->targetList) != 1)
5461 goto fail;
5462
5463 /* If the function result is composite, resolve it */
5465 NULL,
5466 &rettupdesc);
5467
5468 /*
5469 * Make sure the function (still) returns what it's declared to. This
5470 * will raise an error if wrong, but that's okay since the function would
5471 * fail at runtime anyway. Note that check_sql_fn_retval will also insert
5472 * a coercion if needed to make the tlist expression match the declared
5473 * type of the function.
5474 *
5475 * Note: we do not try this until we have verified that no rewriting was
5476 * needed; that's probably not important, but let's be careful.
5477 */
5480 result_type, rettupdesc,
5481 funcform->prokind,
5482 false))
5483 goto fail; /* reject whole-tuple-result cases */
5484
5485 /*
5486 * Given the tests above, check_sql_fn_retval shouldn't have decided to
5487 * inject a projection step, but let's just make sure.
5488 */
5490 goto fail;
5491
5492 /* Now we can grab the tlist expression */
5493 newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
5494
5495 /*
5496 * If the SQL function returns VOID, we can only inline it if it is a
5497 * SELECT of an expression returning VOID (ie, it's just a redirection to
5498 * another VOID-returning function). In all non-VOID-returning cases,
5499 * check_sql_fn_retval should ensure that newexpr returns the function's
5500 * declared result type, so this test shouldn't fail otherwise; but we may
5501 * as well cope gracefully if it does.
5502 */
5503 if (exprType(newexpr) != result_type)
5504 goto fail;
5505
5506 /*
5507 * Additional validity checks on the expression. It mustn't be more
5508 * volatile than the surrounding function (this is to avoid breaking hacks
5509 * that involve pretending a function is immutable when it really ain't).
5510 * If the surrounding function is declared strict, then the expression
5511 * must contain only strict constructs and must use all of the function
5512 * parameters (this is overkill, but an exact analysis is hard).
5513 */
5514 if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
5516 goto fail;
5517 else if (funcform->provolatile == PROVOLATILE_STABLE &&
5519 goto fail;
5520
5521 if (funcform->proisstrict &&
5523 goto fail;
5524
5525 /*
5526 * If any parameter expression contains a context-dependent node, we can't
5527 * inline, for fear of putting such a node into the wrong context.
5528 */
5530 goto fail;
5531
5532 /*
5533 * We may be able to do it; there are still checks on parameter usage to
5534 * make, but those are most easily done in combination with the actual
5535 * substitution of the inputs. So start building expression with inputs
5536 * substituted.
5537 */
5538 usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
5540 args, usecounts);
5541
5542 /* Now check for parameter usage */
5543 i = 0;
5544 foreach(arg, args)
5545 {
5546 Node *param = lfirst(arg);
5547
5548 if (usecounts[i] == 0)
5549 {
5550 /* Param not used at all: uncool if func is strict */
5551 if (funcform->proisstrict)
5552 goto fail;
5553 }
5554 else if (usecounts[i] != 1)
5555 {
5556 /* Param used multiple times: uncool if expensive or volatile */
5558
5559 /*
5560 * We define "expensive" as "contains any subplan or more than 10
5561 * operators". Note that the subplan search has to be done
5562 * explicitly, since cost_qual_eval() will barf on unplanned
5563 * subselects.
5564 */
5565 if (contain_subplans(param))
5566 goto fail;
5568 if (eval_cost.startup + eval_cost.per_tuple >
5569 10 * cpu_operator_cost)
5570 goto fail;
5571
5572 /*
5573 * Check volatility last since this is more expensive than the
5574 * above tests
5575 */
5576 if (contain_volatile_functions(param))
5577 goto fail;
5578 }
5579 i++;
5580 }
5581
5582 /*
5583 * Whew --- we can make the substitution. Copy the modified expression
5584 * out of the temporary memory context, and clean up.
5585 */
5587
5589
5591
5592 /*
5593 * If the result is of a collatable type, force the result to expose the
5594 * correct collation. In most cases this does not matter, but it's
5595 * possible that the function result is used directly as a sort key or in
5596 * other places where we expect exprCollation() to tell the truth.
5597 */
5599 {
5601
5603 {
5605
5606 newnode->arg = (Expr *) newexpr;
5607 newnode->collOid = result_collid;
5608 newnode->location = -1;
5609
5610 newexpr = (Node *) newnode;
5611 }
5612 }
5613
5614 /*
5615 * Since there is now no trace of the function in the plan tree, we must
5616 * explicitly record the plan's dependency on the function.
5617 */
5618 if (context->root)
5619 record_plan_function_dependency(context->root, funcid);
5620
5621 /*
5622 * Recursively try to simplify the modified expression. Here we must add
5623 * the current function to the context list of active functions.
5624 */
5625 context->active_fns = lappend_oid(context->active_fns, funcid);
5627 context->active_fns = list_delete_last(context->active_fns);
5628
5630
5631 return (Expr *) newexpr;
5632
5633 /* Here if func is not inlinable: release temp memory and return NULL */
5634fail:
5638
5639 return NULL;
5640}

References ACL_EXECUTE, ACLCHECK_OK, eval_const_expressions_context::active_fns, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, arg, castNode, check_sql_fn_retval(), CMD_SELECT, COERCE_EXPLICIT_CALL, contain_context_dependent_node(), contain_mutable_functions(), contain_nonstrict_functions(), contain_subplans(), contain_volatile_functions(), copyObject, cost_qual_eval(), cpu_operator_cost, CurrentMemoryContext, error_context_stack, eval_const_expressions_mutator(), exprCollation(), exprType(), fb(), FmgrHookIsNeeded, Form_pg_proc, free_parsestate(), get_expr_result_type(), GETSTRUCT(), GetUserId(), heap_attisnull(), i, IsA, lappend_oid(), lfirst, linitial, linitial_node, list_delete_last(), list_length(), list_make1, list_member_oid(), make_parsestate(), makeNode, MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, object_aclcheck(), OidIsValid, ParseState::p_sourcetext, palloc0(), pg_parse_query(), prepare_sql_fn_parse_info(), ErrorContextCallback::previous, inline_error_callback_arg::proname, inline_error_callback_arg::prosrc, querytree(), record_plan_function_dependency(), eval_const_expressions_context::root, sql_fn_parser_setup(), sql_inline_error_callback(), stringToNode(), substitute_actual_parameters(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, and transformTopLevelStmt().

Referenced by simplify_function().

◆ inline_function_in_from()

Query * inline_function_in_from ( PlannerInfo root,
RangeTblEntry rte 
)

Definition at line 5803 of file clauses.c.

5804{
5805 RangeTblFunction *rtfunc;
5806 FuncExpr *fexpr;
5807 Oid func_oid;
5812 Datum tmp;
5813 char *src;
5814 inline_error_callback_arg callback_arg;
5816 Query *querytree = NULL;
5817
5818 Assert(rte->rtekind == RTE_FUNCTION);
5819
5820 /*
5821 * Guard against infinite recursion during expansion by checking for stack
5822 * overflow. (There's no need to do more.)
5823 */
5825
5826 /* Fail if the RTE has ORDINALITY - we don't implement that here. */
5827 if (rte->funcordinality)
5828 return NULL;
5829
5830 /* Fail if RTE isn't a single, simple FuncExpr */
5831 if (list_length(rte->functions) != 1)
5832 return NULL;
5833 rtfunc = (RangeTblFunction *) linitial(rte->functions);
5834
5835 if (!IsA(rtfunc->funcexpr, FuncExpr))
5836 return NULL;
5837 fexpr = (FuncExpr *) rtfunc->funcexpr;
5838
5839 func_oid = fexpr->funcid;
5840
5841 /*
5842 * Refuse to inline if the arguments contain any volatile functions or
5843 * sub-selects. Volatile functions are rejected because inlining may
5844 * result in the arguments being evaluated multiple times, risking a
5845 * change in behavior. Sub-selects are rejected partly for implementation
5846 * reasons (pushing them down another level might change their behavior)
5847 * and partly because they're likely to be expensive and so multiple
5848 * evaluation would be bad.
5849 */
5850 if (contain_volatile_functions((Node *) fexpr->args) ||
5851 contain_subplans((Node *) fexpr->args))
5852 return NULL;
5853
5854 /* Check permission to call function (fail later, if not) */
5856 return NULL;
5857
5858 /* Check whether a plugin wants to hook function entry/exit */
5860 return NULL;
5861
5862 /*
5863 * OK, let's take a look at the function's pg_proc entry.
5864 */
5867 elog(ERROR, "cache lookup failed for function %u", func_oid);
5869
5870 /*
5871 * If the function SETs any configuration parameters, inlining would cause
5872 * us to miss making those changes.
5873 */
5875 {
5877 return NULL;
5878 }
5879
5880 /*
5881 * Make a temporary memory context, so that we don't leak all the stuff
5882 * that parsing and rewriting might create. If we succeed, we'll copy
5883 * just the finished query tree back up to the caller's context.
5884 */
5886 "inline_function_in_from",
5889
5890 /* Fetch the function body */
5892 src = TextDatumGetCString(tmp);
5893
5894 /*
5895 * If the function has an attached support function that can handle
5896 * SupportRequestInlineInFrom, then attempt to inline with that.
5897 */
5898 if (funcform->prosupport)
5899 {
5901
5903 req.root = root;
5904 req.rtfunc = rtfunc;
5905 req.proc = func_tuple;
5906
5907 querytree = (Query *)
5909 PointerGetDatum(&req)));
5910 }
5911
5912 /*
5913 * Setup error traceback support for ereport(). This is so that we can
5914 * finger the function that bad information came from. We don't install
5915 * this while running the support function, since it'd be likely to do the
5916 * wrong thing: any parse errors reported during that are very likely not
5917 * against the raw function source text.
5918 */
5919 callback_arg.proname = NameStr(funcform->proname);
5920 callback_arg.prosrc = src;
5921
5923 sqlerrcontext.arg = &callback_arg;
5926
5927 /*
5928 * If SupportRequestInlineInFrom didn't work, try our built-in inlining
5929 * mechanism.
5930 */
5931 if (!querytree)
5933 func_tuple, funcform, src);
5934
5935 if (!querytree)
5936 goto fail; /* no luck there either, fail */
5937
5938 /*
5939 * The result had better be a SELECT Query.
5940 */
5942 Assert(querytree->commandType == CMD_SELECT);
5943
5944 /*
5945 * Looks good --- substitute parameters into the query.
5946 */
5948 funcform->pronargs,
5949 fexpr->args);
5950
5951 /*
5952 * Copy the modified query out of the temporary memory context, and clean
5953 * up.
5954 */
5956
5958
5962
5963 /*
5964 * We don't have to fix collations here because the upper query is already
5965 * parsed, ie, the collations in the RTE are what count.
5966 */
5967
5968 /*
5969 * Since there is now no trace of the function in the plan tree, we must
5970 * explicitly record the plan's dependency on the function.
5971 */
5973
5974 /*
5975 * We must also notice if the inserted query adds a dependency on the
5976 * calling role due to RLS quals.
5977 */
5978 if (querytree->hasRowSecurity)
5979 root->glob->dependsOnRole = true;
5980
5981 return querytree;
5982
5983 /* Here if func is not inlinable: release temp memory and return NULL */
5984fail:
5989
5990 return NULL;
5991}

References ACL_EXECUTE, ACLCHECK_OK, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, check_stack_depth(), CMD_SELECT, contain_subplans(), contain_volatile_functions(), copyObject, CurrentMemoryContext, DatumGetPointer(), elog, ERROR, error_context_stack, fb(), FmgrHookIsNeeded, Form_pg_proc, RangeTblFunction::funcexpr, GETSTRUCT(), GetUserId(), heap_attisnull(), HeapTupleIsValid, inline_sql_function_in_from(), IsA, linitial, list_length(), MemoryContextDelete(), MemoryContextSwitchTo(), NameStr, object_aclcheck(), ObjectIdGetDatum(), OidFunctionCall1, PointerGetDatum, ErrorContextCallback::previous, inline_error_callback_arg::proname, inline_error_callback_arg::prosrc, querytree(), record_plan_function_dependency(), ReleaseSysCache(), root, RTE_FUNCTION, SearchSysCache1(), sql_inline_error_callback(), substitute_actual_parameters_in_from(), SysCacheGetAttrNotNull(), TextDatumGetCString, and SupportRequestInlineInFrom::type.

Referenced by preprocess_function_rtes().

◆ inline_sql_function_in_from()

static Query * inline_sql_function_in_from ( PlannerInfo root,
RangeTblFunction rtfunc,
FuncExpr fexpr,
HeapTuple  func_tuple,
Form_pg_proc  funcform,
const char src 
)
static

Definition at line 6007 of file clauses.c.

6013{
6014 Datum sqlbody;
6015 bool isNull;
6019 TupleDesc rettupdesc;
6020
6021 /*
6022 * The function must be declared to return a set, else inlining would
6023 * change the results if the contained SELECT didn't return exactly one
6024 * row.
6025 */
6026 if (!fexpr->funcretset)
6027 return NULL;
6028
6029 /*
6030 * Forget it if the function is not SQL-language or has other showstopper
6031 * properties. In particular it mustn't be declared STRICT, since we
6032 * couldn't enforce that. It also mustn't be VOLATILE, because that is
6033 * supposed to cause it to be executed with its own snapshot, rather than
6034 * sharing the snapshot of the calling query. We also disallow returning
6035 * SETOF VOID, because inlining would result in exposing the actual result
6036 * of the function's last SELECT, which should not happen in that case.
6037 * (Rechecking prokind, proretset, and pronargs is just paranoia.)
6038 */
6039 if (funcform->prolang != SQLlanguageId ||
6040 funcform->prokind != PROKIND_FUNCTION ||
6041 funcform->proisstrict ||
6042 funcform->provolatile == PROVOLATILE_VOLATILE ||
6043 funcform->prorettype == VOIDOID ||
6044 funcform->prosecdef ||
6045 !funcform->proretset ||
6046 list_length(fexpr->args) != funcform->pronargs)
6047 return NULL;
6048
6049 /* If we have prosqlbody, pay attention to that not prosrc */
6051 func_tuple,
6053 &isNull);
6054 if (!isNull)
6055 {
6056 Node *n;
6057
6059 if (IsA(n, List))
6061 else
6063 if (list_length(querytree_list) != 1)
6064 return NULL;
6066
6067 /* Acquire necessary locks, then apply rewriter. */
6068 AcquireRewriteLocks(querytree, true, false);
6070 if (list_length(querytree_list) != 1)
6071 return NULL;
6073 }
6074 else
6075 {
6078
6079 /*
6080 * Set up to handle parameters while parsing the function body. We
6081 * can use the FuncExpr just created as the input for
6082 * prepare_sql_fn_parse_info.
6083 */
6085 (Node *) fexpr,
6086 fexpr->inputcollid);
6087
6088 /*
6089 * Parse, analyze, and rewrite (unlike inline_function(), we can't
6090 * skip rewriting here). We can fail as soon as we find more than one
6091 * query, though.
6092 */
6095 return NULL;
6096
6098 src,
6100 pinfo, NULL);
6101 if (list_length(querytree_list) != 1)
6102 return NULL;
6104 }
6105
6106 /*
6107 * Also resolve the actual function result tupdesc, if composite. If we
6108 * have a coldeflist, believe that; otherwise use get_expr_result_type.
6109 * (This logic should match ExecInitFunctionScan.)
6110 */
6111 if (rtfunc->funccolnames != NIL)
6112 {
6114 rettupdesc = BuildDescFromLists(rtfunc->funccolnames,
6115 rtfunc->funccoltypes,
6116 rtfunc->funccoltypmods,
6117 rtfunc->funccolcollations);
6118 }
6119 else
6120 functypclass = get_expr_result_type((Node *) fexpr, NULL, &rettupdesc);
6121
6122 /*
6123 * The single command must be a plain SELECT.
6124 */
6125 if (!IsA(querytree, Query) ||
6126 querytree->commandType != CMD_SELECT)
6127 return NULL;
6128
6129 /*
6130 * Make sure the function (still) returns what it's declared to. This
6131 * will raise an error if wrong, but that's okay since the function would
6132 * fail at runtime anyway. Note that check_sql_fn_retval will also insert
6133 * coercions if needed to make the tlist expression(s) match the declared
6134 * type of the function. We also ask it to insert dummy NULL columns for
6135 * any dropped columns in rettupdesc, so that the elements of the modified
6136 * tlist match up to the attribute numbers.
6137 *
6138 * If the function returns a composite type, don't inline unless the check
6139 * shows it's returning a whole tuple result; otherwise what it's
6140 * returning is a single composite column which is not what we need.
6141 */
6143 fexpr->funcresulttype, rettupdesc,
6144 funcform->prokind,
6145 true) &&
6149 return NULL; /* reject not-whole-tuple-result cases */
6150
6151 /*
6152 * check_sql_fn_retval might've inserted a projection step, but that's
6153 * fine; just make sure we use the upper Query.
6154 */
6156
6157 return querytree;
6158}

References AcquireRewriteLocks(), BuildDescFromLists(), castNode, check_sql_fn_retval(), CMD_SELECT, fb(), get_expr_result_type(), IsA, linitial, linitial_node, list_length(), list_make1, NIL, pg_analyze_and_rewrite_withcb(), pg_parse_query(), pg_rewrite_query(), prepare_sql_fn_parse_info(), querytree(), sql_fn_parser_setup(), stringToNode(), SysCacheGetAttr(), TextDatumGetCString, TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, and TYPEFUNC_RECORD.

Referenced by inline_function_in_from().

◆ is_parallel_safe()

bool is_parallel_safe ( PlannerInfo root,
Node node 
)

Definition at line 766 of file clauses.c.

767{
770 ListCell *l;
771
772 /*
773 * Even if the original querytree contained nothing unsafe, we need to
774 * search the expression if we have generated any PARAM_EXEC Params while
775 * planning, because those are parallel-restricted and there might be one
776 * in this expression. But otherwise we don't need to look.
777 */
778 if (root->glob->maxParallelHazard == PROPARALLEL_SAFE &&
779 root->glob->paramExecTypes == NIL)
780 return true;
781 /* Else use max_parallel_hazard's search logic, but stop on RESTRICTED */
784 context.safe_param_ids = NIL;
785
786 /*
787 * The params that refer to the same or parent query level are considered
788 * parallel-safe. The idea is that we compute such params at Gather or
789 * Gather Merge node and pass their value to workers.
790 */
791 for (proot = root; proot != NULL; proot = proot->parent_root)
792 {
793 foreach(l, proot->init_plans)
794 {
796
797 context.safe_param_ids = list_concat(context.safe_param_ids,
798 initsubplan->setParam);
799 }
800 }
801
802 return !max_parallel_hazard_walker(node, &context);
803}
static bool max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
Definition clauses.c:842
List * list_concat(List *list1, const List *list2)
Definition list.c:561

References fb(), lfirst, list_concat(), max_parallel_hazard_context::max_hazard, max_parallel_hazard_context::max_interesting, max_parallel_hazard_walker(), NIL, root, and max_parallel_hazard_context::safe_param_ids.

Referenced by apply_projection_to_path(), build_join_rel(), create_minmaxagg_path(), create_nestloop_plan(), create_partial_unique_paths(), create_projection_path(), create_set_projection_path(), create_window_paths(), find_computable_ec_member(), grouping_planner(), make_grouping_rel(), plan_create_index_workers(), query_planner(), relation_can_be_sorted_early(), and set_rel_consider_parallel().

◆ is_pseudo_constant_clause()

bool is_pseudo_constant_clause ( Node clause)

Definition at line 2333 of file clauses.c.

2334{
2335 /*
2336 * We could implement this check in one recursive scan. But since the
2337 * check for volatile functions is both moderately expensive and unlikely
2338 * to fail, it seems better to look for Vars first and only check for
2339 * volatile functions if we find no Vars.
2340 */
2341 if (!contain_var_clause(clause) &&
2343 return true;
2344 return false;
2345}

References contain_var_clause(), and contain_volatile_functions().

Referenced by clauselist_selectivity_ext(), dependency_is_compatible_clause(), dependency_is_compatible_expression(), and find_window_run_conditions().

◆ is_pseudo_constant_clause_relids()

bool is_pseudo_constant_clause_relids ( Node clause,
Relids  relids 
)

Definition at line 2353 of file clauses.c.

2354{
2355 if (bms_is_empty(relids) &&
2357 return true;
2358 return false;
2359}

References bms_is_empty, and contain_volatile_functions().

Referenced by clauselist_selectivity_ext().

◆ is_strict_saop()

static bool is_strict_saop ( ScalarArrayOpExpr expr,
bool  falseOK 
)
static

Definition at line 2271 of file clauses.c.

2272{
2273 Node *rightop;
2274
2275 /* The contained operator must be strict. */
2276 set_sa_opfuncid(expr);
2277 if (!func_strict(expr->opfuncid))
2278 return false;
2279 /* If ANY and falseOK, that's all we need to check. */
2280 if (expr->useOr && falseOK)
2281 return true;
2282 /* Else, we have to see if the array is provably non-empty. */
2283 Assert(list_length(expr->args) == 2);
2284 rightop = (Node *) lsecond(expr->args);
2285 if (rightop && IsA(rightop, Const))
2286 {
2287 Datum arraydatum = ((Const *) rightop)->constvalue;
2288 bool arrayisnull = ((Const *) rightop)->constisnull;
2290 int nitems;
2291
2292 if (arrayisnull)
2293 return false;
2296 if (nitems > 0)
2297 return true;
2298 }
2299 else if (rightop && IsA(rightop, ArrayExpr))
2300 {
2301 ArrayExpr *arrayexpr = (ArrayExpr *) rightop;
2302
2303 if (arrayexpr->elements != NIL && !arrayexpr->multidims)
2304 return true;
2305 }
2306 return false;
2307}

References ScalarArrayOpExpr::args, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), Assert, DatumGetArrayTypeP, fb(), func_strict(), IsA, list_length(), lsecond, NIL, nitems, set_sa_opfuncid(), and ScalarArrayOpExpr::useOr.

Referenced by find_nonnullable_rels_walker(), and find_nonnullable_vars_walker().

◆ make_SAOP_expr()

ScalarArrayOpExpr * make_SAOP_expr ( Oid  oper,
Node leftexpr,
Oid  coltype,
Oid  arraycollid,
Oid  inputcollid,
List exprs,
bool  haveNonConst 
)

Definition at line 6259 of file clauses.c.

6261{
6262 Node *arrayNode = NULL;
6264 Oid arraytype = get_array_type(coltype);
6265
6266 if (!OidIsValid(arraytype))
6267 return NULL;
6268
6269 /*
6270 * Assemble an array from the list of constants. It seems more profitable
6271 * to build a const array. But in the presence of other nodes, we don't
6272 * have a specific value here and must employ an ArrayExpr instead.
6273 */
6274 if (haveNonConst)
6275 {
6277
6278 /* array_collid will be set by parse_collate.c */
6279 arrayExpr->element_typeid = coltype;
6280 arrayExpr->array_typeid = arraytype;
6281 arrayExpr->multidims = false;
6282 arrayExpr->elements = exprs;
6283 arrayExpr->location = -1;
6284
6285 arrayNode = (Node *) arrayExpr;
6286 }
6287 else
6288 {
6289 int16 typlen;
6290 bool typbyval;
6291 char typalign;
6292 Datum *elems;
6293 bool *nulls;
6294 int i = 0;
6296 int dims[1] = {list_length(exprs)};
6297 int lbs[1] = {1};
6298
6299 get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign);
6300
6301 elems = palloc_array(Datum, list_length(exprs));
6302 nulls = palloc_array(bool, list_length(exprs));
6303 foreach_node(Const, value, exprs)
6304 {
6305 elems[i] = value->constvalue;
6306 nulls[i++] = value->constisnull;
6307 }
6308
6309 arrayConst = construct_md_array(elems, nulls, 1, dims, lbs,
6310 coltype, typlen, typbyval, typalign);
6313 false, false);
6314
6315 pfree(elems);
6316 pfree(nulls);
6317 list_free(exprs);
6318 }
6319
6320 /* Build the SAOP expression node */
6322 saopexpr->opno = oper;
6323 saopexpr->opfuncid = get_opcode(oper);
6324 saopexpr->hashfuncid = InvalidOid;
6325 saopexpr->negfuncid = InvalidOid;
6326 saopexpr->useOr = true;
6327 saopexpr->inputcollid = inputcollid;
6329 saopexpr->location = -1;
6330
6331 return saopexpr;
6332}

References construct_md_array(), fb(), foreach_node, get_array_type(), get_opcode(), get_typlenbyvalalign(), i, InvalidOid, list_free(), list_length(), list_make2, makeConst(), makeNode, OidIsValid, oper(), palloc_array, pfree(), PointerGetDatum, typalign, and value.

Referenced by convert_VALUES_to_ANY(), and match_orclause_to_indexcol().

◆ max_parallel_hazard()

char max_parallel_hazard ( Query parse)

◆ max_parallel_hazard_checker()

static bool max_parallel_hazard_checker ( Oid  func_id,
void context 
)
static

Definition at line 835 of file clauses.c.

836{
838 (max_parallel_hazard_context *) context);
839}
static bool max_parallel_hazard_test(char proparallel, max_parallel_hazard_context *context)
Definition clauses.c:807
char func_parallel(Oid funcid)
Definition lsyscache.c:1992

References fb(), func_parallel(), and max_parallel_hazard_test().

Referenced by max_parallel_hazard_walker().

◆ max_parallel_hazard_test()

static bool max_parallel_hazard_test ( char  proparallel,
max_parallel_hazard_context context 
)
static

Definition at line 807 of file clauses.c.

808{
809 switch (proparallel)
810 {
811 case PROPARALLEL_SAFE:
812 /* nothing to see here, move along */
813 break;
815 /* increase max_hazard to RESTRICTED */
817 context->max_hazard = proparallel;
818 /* done if we are not expecting any unsafe functions */
819 if (context->max_interesting == proparallel)
820 return true;
821 break;
823 context->max_hazard = proparallel;
824 /* we're always done at the first unsafe construct */
825 return true;
826 default:
827 elog(ERROR, "unrecognized proparallel value \"%c\"", proparallel);
828 break;
829 }
830 return false;
831}

References Assert, elog, ERROR, fb(), max_parallel_hazard_context::max_hazard, and max_parallel_hazard_context::max_interesting.

Referenced by max_parallel_hazard_checker(), and max_parallel_hazard_walker().

◆ max_parallel_hazard_walker()

static bool max_parallel_hazard_walker ( Node node,
max_parallel_hazard_context context 
)
static

Definition at line 842 of file clauses.c.

843{
844 if (node == NULL)
845 return false;
846
847 /* Check for hazardous functions in node itself */
849 context))
850 return true;
851
852 /*
853 * It should be OK to treat MinMaxExpr as parallel-safe, since btree
854 * opclass support functions are generally parallel-safe. XmlExpr is a
855 * bit more dubious but we can probably get away with it. We err on the
856 * side of caution by treating CoerceToDomain as parallel-restricted.
857 * (Note: in principle that's wrong because a domain constraint could
858 * contain a parallel-unsafe function; but useful constraints probably
859 * never would have such, and assuming they do would cripple use of
860 * parallel query in the presence of domain types.) SQLValueFunction
861 * should be safe in all cases. NextValueExpr is parallel-unsafe.
862 */
863 if (IsA(node, CoerceToDomain))
864 {
866 return true;
867 }
868
869 else if (IsA(node, NextValueExpr))
870 {
872 return true;
873 }
874
875 /*
876 * Treat window functions as parallel-restricted because we aren't sure
877 * whether the input row ordering is fully deterministic, and the output
878 * of window functions might vary across workers if not. (In some cases,
879 * like where the window frame orders by a primary key, we could relax
880 * this restriction. But it doesn't currently seem worth expending extra
881 * effort to do so.)
882 */
883 else if (IsA(node, WindowFunc))
884 {
886 return true;
887 }
888
889 /*
890 * As a notational convenience for callers, look through RestrictInfo.
891 */
892 else if (IsA(node, RestrictInfo))
893 {
894 RestrictInfo *rinfo = (RestrictInfo *) node;
895
896 return max_parallel_hazard_walker((Node *) rinfo->clause, context);
897 }
898
899 /*
900 * Really we should not see SubLink during a max_interesting == restricted
901 * scan, but if we do, return true.
902 */
903 else if (IsA(node, SubLink))
904 {
906 return true;
907 }
908
909 /*
910 * Only parallel-safe SubPlans can be sent to workers. Within the
911 * testexpr of the SubPlan, Params representing the output columns of the
912 * subplan can be treated as parallel-safe, so temporarily add their IDs
913 * to the safe_param_ids list while examining the testexpr.
914 */
915 else if (IsA(node, SubPlan))
916 {
917 SubPlan *subplan = (SubPlan *) node;
919
920 if (!subplan->parallel_safe &&
922 return true;
925 subplan->paramIds);
926 if (max_parallel_hazard_walker(subplan->testexpr, context))
927 return true; /* no need to restore safe_param_ids */
928 list_free(context->safe_param_ids);
930 /* we must also check args, but no special Param treatment there */
931 if (max_parallel_hazard_walker((Node *) subplan->args, context))
932 return true;
933 /* don't want to recurse normally, so we're done */
934 return false;
935 }
936
937 /*
938 * We can't pass Params to workers at the moment either, so they are also
939 * parallel-restricted, unless they are PARAM_EXTERN Params or are
940 * PARAM_EXEC Params listed in safe_param_ids, meaning they could be
941 * either generated within workers or can be computed by the leader and
942 * then their value can be passed to workers.
943 */
944 else if (IsA(node, Param))
945 {
946 Param *param = (Param *) node;
947
948 if (param->paramkind == PARAM_EXTERN)
949 return false;
950
951 if (param->paramkind != PARAM_EXEC ||
952 !list_member_int(context->safe_param_ids, param->paramid))
953 {
955 return true;
956 }
957 return false; /* nothing to recurse to */
958 }
959
960 /*
961 * When we're first invoked on a completely unplanned tree, we must
962 * recurse into subqueries so to as to locate parallel-unsafe constructs
963 * anywhere in the tree.
964 */
965 else if (IsA(node, Query))
966 {
967 Query *query = (Query *) node;
968
969 /* SELECT FOR UPDATE/SHARE must be treated as unsafe */
970 if (query->rowMarks != NULL)
971 {
973 return true;
974 }
975
976 /* Recurse into subselects */
977 return query_tree_walker(query,
979 context, 0);
980 }
981
982 /* Recurse to check arguments */
983 return expression_tree_walker(node,
985 context);
986}
static bool max_parallel_hazard_checker(Oid func_id, void *context)
Definition clauses.c:835
List * rowMarks
Definition parsenodes.h:237
List * args
Definition primnodes.h:1125
List * paramIds
Definition primnodes.h:1101
bool parallel_safe
Definition primnodes.h:1118

References SubPlan::args, check_functions_in_node(), RestrictInfo::clause, expression_tree_walker, fb(), IsA, list_concat_copy(), list_free(), list_member_int(), max_parallel_hazard_context::max_hazard, max_parallel_hazard_checker(), max_parallel_hazard_test(), max_parallel_hazard_walker(), SubPlan::parallel_safe, PARAM_EXEC, PARAM_EXTERN, Param::paramid, SubPlan::paramIds, Param::paramkind, query_tree_walker, Query::rowMarks, max_parallel_hazard_context::safe_param_ids, and SubPlan::testexpr.

Referenced by is_parallel_safe(), max_parallel_hazard(), and max_parallel_hazard_walker().

◆ NumRelids()

int NumRelids ( PlannerInfo root,
Node clause 
)

Definition at line 2375 of file clauses.c.

2376{
2377 int result;
2378 Relids varnos = pull_varnos(root, clause);
2379
2380 varnos = bms_del_members(varnos, root->outer_join_rels);
2381 result = bms_num_members(varnos);
2382 bms_free(varnos);
2383 return result;
2384}
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1145
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:744
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition var.c:114

References bms_del_members(), bms_free(), bms_num_members(), pull_varnos(), result, and root.

Referenced by clauselist_selectivity_ext(), rowcomparesel(), and treat_as_join_clause().

◆ pull_paramids()

Bitmapset * pull_paramids ( Expr expr)

Definition at line 6227 of file clauses.c.

6228{
6230
6231 (void) pull_paramids_walker((Node *) expr, &result);
6232
6233 return result;
6234}

References fb(), pull_paramids_walker(), and result.

Referenced by create_memoize_plan().

◆ pull_paramids_walker()

static bool pull_paramids_walker ( Node node,
Bitmapset **  context 
)
static

Definition at line 6237 of file clauses.c.

6238{
6239 if (node == NULL)
6240 return false;
6241 if (IsA(node, Param))
6242 {
6243 Param *param = (Param *) node;
6244
6245 *context = bms_add_member(*context, param->paramid);
6246 return false;
6247 }
6248 return expression_tree_walker(node, pull_paramids_walker, context);
6249}

References bms_add_member(), expression_tree_walker, fb(), IsA, Param::paramid, and pull_paramids_walker().

Referenced by pull_paramids(), and pull_paramids_walker().

◆ query_outputs_are_not_nullable()

bool query_outputs_are_not_nullable ( Query query)

Definition at line 2051 of file clauses.c.

2052{
2053 PlannerInfo subroot;
2054 List *safe_quals = NIL;
2056 bool computed_nonnullable_vars = false;
2057
2058 /*
2059 * If the query contains set operations, punt. The set ops themselves
2060 * couldn't introduce nulls that weren't in their inputs, but the tlist
2061 * present in the top-level query is just dummy and won't give us useful
2062 * info. We could get an answer by recursing to examine each leaf query,
2063 * but for the moment it doesn't seem worth the extra complication.
2064 */
2065 if (query->setOperations)
2066 return false;
2067
2068 /*
2069 * If the query contains grouping sets, punt. Grouping sets can introduce
2070 * NULL values, and we currently lack the PlannerInfo needed to flatten
2071 * grouping Vars in the query's outputs.
2072 */
2073 if (query->groupingSets)
2074 return false;
2075
2076 /*
2077 * We need a PlannerInfo to pass to expr_is_nonnullable. Fortunately, we
2078 * can cons up an entirely dummy one, because only the "parse" link in the
2079 * struct is used by expr_is_nonnullable.
2080 */
2081 MemSet(&subroot, 0, sizeof(subroot));
2082 subroot.parse = query;
2083
2084 /*
2085 * Examine each targetlist entry to prove that it can't produce NULL.
2086 */
2088 {
2089 Expr *expr = tle->expr;
2090
2091 /* Resjunk columns can be ignored: they don't produce output values */
2092 if (tle->resjunk)
2093 continue;
2094
2095 /*
2096 * Look through binary relabelings, since we know those don't
2097 * introduce nulls.
2098 */
2099 while (expr && IsA(expr, RelabelType))
2100 expr = ((RelabelType *) expr)->arg;
2101
2102 if (expr == NULL) /* paranoia */
2103 return false;
2104
2105 /*
2106 * Since the subquery hasn't yet been through expression
2107 * preprocessing, we must explicitly flatten grouping Vars and join
2108 * alias Vars in the given expression. Note that flatten_group_exprs
2109 * must be applied before flatten_join_alias_vars, as grouping Vars
2110 * can wrap join alias Vars.
2111 *
2112 * We must also apply flatten_join_alias_vars to the quals extracted
2113 * by find_subquery_safe_quals. We do not need to apply
2114 * flatten_group_exprs to these quals, though, because grouping Vars
2115 * cannot appear in jointree quals.
2116 */
2117
2118 /*
2119 * We have verified that the query does not contain grouping sets,
2120 * meaning the grouping Vars will not have varnullingrels that need
2121 * preserving, so it's safe to use NULL as the root here.
2122 */
2123 if (query->hasGroupRTE)
2124 expr = (Expr *) flatten_group_exprs(NULL, query, (Node *) expr);
2125
2126 /*
2127 * We won't be dealing with arbitrary expressions, so it's safe to use
2128 * NULL as the root, so long as adjust_standard_join_alias_expression
2129 * can handle everything the parser would make as a join alias
2130 * expression.
2131 */
2132 expr = (Expr *) flatten_join_alias_vars(NULL, query, (Node *) expr);
2133
2134 /*
2135 * Check to see if the expr cannot be NULL. Since we're on a raw
2136 * parse tree, we need to look up the not-null constraints from the
2137 * system catalogs.
2138 */
2139 if (expr_is_nonnullable(&subroot, expr, NOTNULL_SOURCE_CATALOG))
2140 continue;
2141
2142 if (IsA(expr, Var))
2143 {
2144 Var *var = (Var *) expr;
2145
2146 /*
2147 * For a plain Var, even if that didn't work, we can conclude that
2148 * the Var is not nullable if find_nonnullable_vars can find a
2149 * "var IS NOT NULL" or similarly strict condition among the quals
2150 * on non-outerjoined-rels. Compute the list of Vars having such
2151 * quals if we didn't already.
2152 */
2154 {
2156 safe_quals = (List *)
2160 }
2161
2162 if (!mbms_is_member(var->varno,
2165 return false; /* we failed to prove the Var non-null */
2166 }
2167 else
2168 {
2169 /* Punt otherwise */
2170 return false;
2171 }
2172 }
2173
2174 return true;
2175}
#define MemSet(start, val, len)
Definition c.h:1107
List * find_nonnullable_vars(Node *clause)
Definition clauses.c:1727
bool mbms_is_member(int listidx, int bitidx, const List *a)
Query * parse
Definition pathnodes.h:309
FromExpr * jointree
Definition parsenodes.h:185
Node * setOperations
Definition parsenodes.h:239
List * targetList
Definition parsenodes.h:201
List * groupingSets
Definition parsenodes.h:223
Node * flatten_group_exprs(PlannerInfo *root, Query *query, Node *node)
Definition var.c:999
Node * flatten_join_alias_vars(PlannerInfo *root, Query *query, Node *node)
Definition var.c:781

References expr_is_nonnullable(), fb(), find_nonnullable_vars(), find_subquery_safe_quals(), FirstLowInvalidHeapAttributeNumber, flatten_group_exprs(), flatten_join_alias_vars(), foreach_node, Query::groupingSets, IsA, Query::jointree, mbms_is_member(), MemSet, NIL, NOTNULL_SOURCE_CATALOG, PlannerInfo::parse, Query::setOperations, Query::targetList, Var::varattno, and Var::varno.

Referenced by convert_ANY_sublink_to_join().

◆ recheck_cast_function_args()

static void recheck_cast_function_args ( List args,
Oid  result_type,
Oid proargtypes,
int  pronargs,
HeapTuple  func_tuple 
)
static

Definition at line 5119 of file clauses.c.

5122{
5124 int nargs;
5127 Oid rettype;
5128 ListCell *lc;
5129
5130 if (list_length(args) > FUNC_MAX_ARGS)
5131 elog(ERROR, "too many function arguments");
5132 nargs = 0;
5133 foreach(lc, args)
5134 {
5135 actual_arg_types[nargs++] = exprType((Node *) lfirst(lc));
5136 }
5137 Assert(nargs == pronargs);
5141 nargs,
5142 funcform->prorettype,
5143 false);
5144 /* let's just check we got the same answer as the parser did ... */
5145 if (rettype != result_type)
5146 elog(ERROR, "function's resolved result type changed during planning");
5147
5148 /* perform any necessary typecasting of arguments */
5150}

References Assert, elog, enforce_generic_type_consistency(), ERROR, exprType(), fb(), Form_pg_proc, FUNC_MAX_ARGS, GETSTRUCT(), lfirst, list_length(), make_fn_arguments(), memcpy(), and pronargs.

Referenced by expand_function_arguments().

◆ reorder_function_arguments()

static List * reorder_function_arguments ( List args,
int  pronargs,
HeapTuple  func_tuple 
)
static

Definition at line 4995 of file clauses.c.

4996{
4998 int nargsprovided = list_length(args);
5000 ListCell *lc;
5001 int i;
5002
5005 elog(ERROR, "too many function arguments");
5006 memset(argarray, 0, pronargs * sizeof(Node *));
5007
5008 /* Deconstruct the argument list into an array indexed by argnumber */
5009 i = 0;
5010 foreach(lc, args)
5011 {
5012 Node *arg = (Node *) lfirst(lc);
5013
5014 if (!IsA(arg, NamedArgExpr))
5015 {
5016 /* positional argument, assumed to precede all named args */
5017 Assert(argarray[i] == NULL);
5018 argarray[i++] = arg;
5019 }
5020 else
5021 {
5023
5024 Assert(na->argnumber >= 0 && na->argnumber < pronargs);
5025 Assert(argarray[na->argnumber] == NULL);
5026 argarray[na->argnumber] = (Node *) na->arg;
5027 }
5028 }
5029
5030 /*
5031 * Fetch default expressions, if needed, and insert into array at proper
5032 * locations (they aren't necessarily consecutive or all used)
5033 */
5034 if (nargsprovided < pronargs)
5035 {
5037
5038 i = pronargs - funcform->pronargdefaults;
5039 foreach(lc, defaults)
5040 {
5041 if (argarray[i] == NULL)
5042 argarray[i] = (Node *) lfirst(lc);
5043 i++;
5044 }
5045 }
5046
5047 /* Now reconstruct the args list in proper order */
5048 args = NIL;
5049 for (i = 0; i < pronargs; i++)
5050 {
5051 Assert(argarray[i] != NULL);
5052 args = lappend(args, argarray[i]);
5053 }
5054
5055 return args;
5056}

References arg, Assert, elog, ERROR, fb(), fetch_function_defaults(), Form_pg_proc, FUNC_MAX_ARGS, GETSTRUCT(), i, IsA, lappend(), lfirst, list_length(), NIL, and pronargs.

Referenced by expand_function_arguments().

◆ rowtype_field_matches()

static bool rowtype_field_matches ( Oid  rowtypeid,
int  fieldnum,
Oid  expectedtype,
int32  expectedtypmod,
Oid  expectedcollation 
)
static

Definition at line 2431 of file clauses.c.

2434{
2435 TupleDesc tupdesc;
2436 Form_pg_attribute attr;
2437
2438 /* No issue for RECORD, since there is no way to ALTER such a type */
2439 if (rowtypeid == RECORDOID)
2440 return true;
2441 tupdesc = lookup_rowtype_tupdesc_domain(rowtypeid, -1, false);
2443 {
2444 ReleaseTupleDesc(tupdesc);
2445 return false;
2446 }
2447 attr = TupleDescAttr(tupdesc, fieldnum - 1);
2448 if (attr->attisdropped ||
2449 attr->atttypid != expectedtype ||
2450 attr->atttypmod != expectedtypmod ||
2451 attr->attcollation != expectedcollation)
2452 {
2453 ReleaseTupleDesc(tupdesc);
2454 return false;
2455 }
2456 ReleaseTupleDesc(tupdesc);
2457 return true;
2458}
FormData_pg_attribute * Form_pg_attribute
#define ReleaseTupleDesc(tupdesc)
Definition tupdesc.h:240
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
TupleDesc lookup_rowtype_tupdesc_domain(Oid type_id, int32 typmod, bool noError)
Definition typcache.c:2003

References fb(), lookup_rowtype_tupdesc_domain(), TupleDescData::natts, ReleaseTupleDesc, and TupleDescAttr().

Referenced by eval_const_expressions_mutator().

◆ simplify_aggref()

static Node * simplify_aggref ( Aggref aggref,
eval_const_expressions_context context 
)
static

Definition at line 4586 of file clauses.c.

4587{
4589
4591 {
4593 Node *newnode;
4594
4595 /*
4596 * Build a SupportRequestSimplifyAggref node to pass to the support
4597 * function.
4598 */
4600 req.root = context->root;
4601 req.aggref = aggref;
4602
4604 PointerGetDatum(&req)));
4605
4606 /*
4607 * We expect the support function to return either a new Node or NULL
4608 * (when simplification isn't possible).
4609 */
4610 Assert(newnode != (Node *) aggref || newnode == NULL);
4611
4612 if (newnode != NULL)
4613 return newnode;
4614 }
4615
4616 return (Node *) aggref;
4617}

References Aggref::aggfnoid, Assert, DatumGetPointer(), fb(), get_func_support(), OidFunctionCall1, OidIsValid, PointerGetDatum, eval_const_expressions_context::root, and Node::type.

Referenced by eval_const_expressions_mutator().

◆ simplify_and_arguments()

static List * simplify_and_arguments ( List args,
eval_const_expressions_context context,
bool haveNull,
bool forceFalse 
)
static

Definition at line 4317 of file clauses.c.

4320{
4321 List *newargs = NIL;
4323
4324 /* See comments in simplify_or_arguments */
4326 while (unprocessed_args)
4327 {
4329
4331
4332 /* flatten nested ANDs as per above comment */
4333 if (is_andclause(arg))
4334 {
4335 List *subargs = ((BoolExpr *) arg)->args;
4337
4339 /* perhaps-overly-tense code to avoid leaking old lists */
4341 continue;
4342 }
4343
4344 /* If it's not an AND, simplify it */
4346
4347 /*
4348 * It is unlikely but not impossible for simplification of a non-AND
4349 * clause to produce an AND. Recheck, but don't be too tense about it
4350 * since it's not a mainstream case. In particular we don't worry
4351 * about const-simplifying the input twice, nor about list leakage.
4352 */
4353 if (is_andclause(arg))
4354 {
4355 List *subargs = ((BoolExpr *) arg)->args;
4356
4358 continue;
4359 }
4360
4361 /*
4362 * OK, we have a const-simplified non-AND argument. Process it per
4363 * comments above.
4364 */
4365 if (IsA(arg, Const))
4366 {
4367 Const *const_input = (Const *) arg;
4368
4369 if (const_input->constisnull)
4370 *haveNull = true;
4371 else if (!DatumGetBool(const_input->constvalue))
4372 {
4373 *forceFalse = true;
4374
4375 /*
4376 * Once we detect a FALSE result we can just exit the loop
4377 * immediately. However, if we ever add a notion of
4378 * non-removable functions, we'd need to keep scanning.
4379 */
4380 return NIL;
4381 }
4382 /* otherwise, we can drop the constant-true input */
4383 continue;
4384 }
4385
4386 /* else emit the simplified arg into the result list */
4388 }
4389
4390 return newargs;
4391}

References arg, DatumGetBool(), eval_const_expressions_mutator(), fb(), is_andclause(), IsA, lappend(), linitial, list_concat_copy(), list_copy(), list_delete_first(), list_free(), and NIL.

Referenced by eval_const_expressions_mutator().

◆ simplify_boolean_equality()

static Node * simplify_boolean_equality ( Oid  opno,
List args 
)
static

Definition at line 4411 of file clauses.c.

4412{
4413 Node *leftop;
4414 Node *rightop;
4415
4416 Assert(list_length(args) == 2);
4417 leftop = linitial(args);
4418 rightop = lsecond(args);
4419 if (leftop && IsA(leftop, Const))
4420 {
4421 Assert(!((Const *) leftop)->constisnull);
4422 if (opno == BooleanEqualOperator)
4423 {
4424 if (DatumGetBool(((Const *) leftop)->constvalue))
4425 return rightop; /* true = foo */
4426 else
4427 return negate_clause(rightop); /* false = foo */
4428 }
4429 else
4430 {
4431 if (DatumGetBool(((Const *) leftop)->constvalue))
4432 return negate_clause(rightop); /* true <> foo */
4433 else
4434 return rightop; /* false <> foo */
4435 }
4436 }
4437 if (rightop && IsA(rightop, Const))
4438 {
4440 if (opno == BooleanEqualOperator)
4441 {
4443 return leftop; /* foo = true */
4444 else
4445 return negate_clause(leftop); /* foo = false */
4446 }
4447 else
4448 {
4450 return negate_clause(leftop); /* foo <> true */
4451 else
4452 return leftop; /* foo <> false */
4453 }
4454 }
4455 return NULL;
4456}

References Assert, DatumGetBool(), fb(), IsA, linitial, list_length(), lsecond, and negate_clause().

Referenced by eval_const_expressions_mutator().

◆ simplify_function()

static Expr * simplify_function ( Oid  funcid,
Oid  result_type,
int32  result_typmod,
Oid  result_collid,
Oid  input_collid,
List **  args_p,
bool  funcvariadic,
bool  process_args,
bool  allow_non_const,
eval_const_expressions_context context 
)
static

Definition at line 4480 of file clauses.c.

4484{
4485 List *args = *args_p;
4488 Expr *newexpr;
4489
4490 /*
4491 * We have three strategies for simplification: execute the function to
4492 * deliver a constant result, use a transform function to generate a
4493 * substitute node tree, or expand in-line the body of the function
4494 * definition (which only works for simple SQL-language functions, but
4495 * that is a common case). Each case needs access to the function's
4496 * pg_proc tuple, so fetch it just once.
4497 *
4498 * Note: the allow_non_const flag suppresses both the second and third
4499 * strategies; so if !allow_non_const, simplify_function can only return a
4500 * Const or NULL. Argument-list rewriting happens anyway, though.
4501 */
4504 elog(ERROR, "cache lookup failed for function %u", funcid);
4506
4507 /*
4508 * Process the function arguments, unless the caller did it already.
4509 *
4510 * Here we must deal with named or defaulted arguments, and then
4511 * recursively apply eval_const_expressions to the whole argument list.
4512 */
4513 if (process_args)
4514 {
4515 args = expand_function_arguments(args, false, result_type, func_tuple);
4518 context);
4519 /* Argument processing done, give it back to the caller */
4520 *args_p = args;
4521 }
4522
4523 /* Now attempt simplification of the function call proper. */
4524
4525 newexpr = evaluate_function(funcid, result_type, result_typmod,
4527 args, funcvariadic,
4528 func_tuple, context);
4529
4530 if (!newexpr && allow_non_const && OidIsValid(func_form->prosupport))
4531 {
4532 /*
4533 * Build a SupportRequestSimplify node to pass to the support
4534 * function, pointing to a dummy FuncExpr node containing the
4535 * simplified arg list. We use this approach to present a uniform
4536 * interface to the support function regardless of how the target
4537 * function is actually being invoked.
4538 */
4541
4542 fexpr.xpr.type = T_FuncExpr;
4543 fexpr.funcid = funcid;
4544 fexpr.funcresulttype = result_type;
4545 fexpr.funcretset = func_form->proretset;
4546 fexpr.funcvariadic = funcvariadic;
4547 fexpr.funcformat = COERCE_EXPLICIT_CALL;
4548 fexpr.funccollid = result_collid;
4549 fexpr.inputcollid = input_collid;
4550 fexpr.args = args;
4551 fexpr.location = -1;
4552
4554 req.root = context->root;
4555 req.fcall = &fexpr;
4556
4557 newexpr = (Expr *)
4559 PointerGetDatum(&req)));
4560
4561 /* catch a possible API misunderstanding */
4562 Assert(newexpr != (Expr *) &fexpr);
4563 }
4564
4565 if (!newexpr && allow_non_const)
4566 newexpr = inline_function(funcid, result_type, result_collid,
4568 func_tuple, context);
4569
4571
4572 return newexpr;
4573}

References Assert, COERCE_EXPLICIT_CALL, DatumGetPointer(), elog, ERROR, eval_const_expressions_mutator(), evaluate_function(), expand_function_arguments(), expression_tree_mutator, fb(), Form_pg_proc, GETSTRUCT(), HeapTupleIsValid, inline_function(), ObjectIdGetDatum(), OidFunctionCall1, OidIsValid, PointerGetDatum, ReleaseSysCache(), eval_const_expressions_context::root, SearchSysCache1(), and FuncExpr::xpr.

Referenced by eval_const_expressions_mutator().

◆ simplify_or_arguments()

static List * simplify_or_arguments ( List args,
eval_const_expressions_context context,
bool haveNull,
bool forceTrue 
)
static

Definition at line 4211 of file clauses.c.

4214{
4215 List *newargs = NIL;
4217
4218 /*
4219 * We want to ensure that any OR immediately beneath another OR gets
4220 * flattened into a single OR-list, so as to simplify later reasoning.
4221 *
4222 * To avoid stack overflow from recursion of eval_const_expressions, we
4223 * resort to some tenseness here: we keep a list of not-yet-processed
4224 * inputs, and handle flattening of nested ORs by prepending to the to-do
4225 * list instead of recursing. Now that the parser generates N-argument
4226 * ORs from simple lists, this complexity is probably less necessary than
4227 * it once was, but we might as well keep the logic.
4228 */
4230 while (unprocessed_args)
4231 {
4233
4235
4236 /* flatten nested ORs as per above comment */
4237 if (is_orclause(arg))
4238 {
4239 List *subargs = ((BoolExpr *) arg)->args;
4241
4243 /* perhaps-overly-tense code to avoid leaking old lists */
4245 continue;
4246 }
4247
4248 /* If it's not an OR, simplify it */
4250
4251 /*
4252 * It is unlikely but not impossible for simplification of a non-OR
4253 * clause to produce an OR. Recheck, but don't be too tense about it
4254 * since it's not a mainstream case. In particular we don't worry
4255 * about const-simplifying the input twice, nor about list leakage.
4256 */
4257 if (is_orclause(arg))
4258 {
4259 List *subargs = ((BoolExpr *) arg)->args;
4260
4262 continue;
4263 }
4264
4265 /*
4266 * OK, we have a const-simplified non-OR argument. Process it per
4267 * comments above.
4268 */
4269 if (IsA(arg, Const))
4270 {
4271 Const *const_input = (Const *) arg;
4272
4273 if (const_input->constisnull)
4274 *haveNull = true;
4275 else if (DatumGetBool(const_input->constvalue))
4276 {
4277 *forceTrue = true;
4278
4279 /*
4280 * Once we detect a TRUE result we can just exit the loop
4281 * immediately. However, if we ever add a notion of
4282 * non-removable functions, we'd need to keep scanning.
4283 */
4284 return NIL;
4285 }
4286 /* otherwise, we can drop the constant-false input */
4287 continue;
4288 }
4289
4290 /* else emit the simplified arg into the result list */
4292 }
4293
4294 return newargs;
4295}

References arg, DatumGetBool(), eval_const_expressions_mutator(), fb(), is_orclause(), IsA, lappend(), linitial, list_concat_copy(), list_copy(), list_delete_first(), list_free(), and NIL.

Referenced by eval_const_expressions_mutator().

◆ sql_inline_error_callback()

static void sql_inline_error_callback ( void arg)
static

Definition at line 5687 of file clauses.c.

5688{
5691
5692 /* If it's a syntax error, convert to internal syntax error report */
5694 if (syntaxerrposition > 0)
5695 {
5696 errposition(0);
5698 internalerrquery(callback_arg->prosrc);
5699 }
5700
5701 errcontext("SQL function \"%s\" during inlining", callback_arg->proname);
5702}

References arg, errcontext, errposition(), fb(), geterrposition(), internalerrposition(), internalerrquery(), inline_error_callback_arg::proname, and inline_error_callback_arg::prosrc.

Referenced by inline_function(), and inline_function_in_from().

◆ substitute_actual_parameters()

static Node * substitute_actual_parameters ( Node expr,
int  nargs,
List args,
int usecounts 
)
static

Definition at line 5646 of file clauses.c.

5648{
5650
5651 context.nargs = nargs;
5652 context.args = args;
5653 context.usecounts = usecounts;
5654
5655 return substitute_actual_parameters_mutator(expr, &context);
5656}

References substitute_actual_parameters_context::args, substitute_actual_parameters_context::nargs, substitute_actual_parameters_mutator(), and substitute_actual_parameters_context::usecounts.

Referenced by inline_function().

◆ substitute_actual_parameters_in_from()

static Query * substitute_actual_parameters_in_from ( Query expr,
int  nargs,
List args 
)
static

◆ substitute_actual_parameters_in_from_mutator()

static Node * substitute_actual_parameters_in_from_mutator ( Node node,
substitute_actual_parameters_in_from_context context 
)
static

Definition at line 6182 of file clauses.c.

6184{
6185 Node *result;
6186
6187 if (node == NULL)
6188 return NULL;
6189 if (IsA(node, Query))
6190 {
6191 context->sublevels_up++;
6192 result = (Node *) query_tree_mutator((Query *) node,
6194 context,
6195 0);
6196 context->sublevels_up--;
6197 return result;
6198 }
6199 if (IsA(node, Param))
6200 {
6201 Param *param = (Param *) node;
6202
6203 if (param->paramkind == PARAM_EXTERN)
6204 {
6205 if (param->paramid <= 0 || param->paramid > context->nargs)
6206 elog(ERROR, "invalid paramid: %d", param->paramid);
6207
6208 /*
6209 * Since the parameter is being inserted into a subquery, we must
6210 * adjust levels.
6211 */
6212 result = copyObject(list_nth(context->args, param->paramid - 1));
6214 return result;
6215 }
6216 }
6217 return expression_tree_mutator(node,
6219 context);
6220}

References substitute_actual_parameters_in_from_context::args, copyObject, elog, ERROR, expression_tree_mutator, fb(), IncrementVarSublevelsUp(), IsA, list_nth(), substitute_actual_parameters_in_from_context::nargs, PARAM_EXTERN, Param::paramid, Param::paramkind, query_tree_mutator, result, substitute_actual_parameters_in_from_context::sublevels_up, and substitute_actual_parameters_in_from_mutator().

Referenced by substitute_actual_parameters_in_from(), and substitute_actual_parameters_in_from_mutator().

◆ substitute_actual_parameters_mutator()

static Node * substitute_actual_parameters_mutator ( Node node,
substitute_actual_parameters_context context 
)
static

Definition at line 5659 of file clauses.c.

5661{
5662 if (node == NULL)
5663 return NULL;
5664 if (IsA(node, Param))
5665 {
5666 Param *param = (Param *) node;
5667
5668 if (param->paramkind != PARAM_EXTERN)
5669 elog(ERROR, "unexpected paramkind: %d", (int) param->paramkind);
5670 if (param->paramid <= 0 || param->paramid > context->nargs)
5671 elog(ERROR, "invalid paramid: %d", param->paramid);
5672
5673 /* Count usage of parameter */
5674 context->usecounts[param->paramid - 1]++;
5675
5676 /* Select the appropriate actual arg and replace the Param with it */
5677 /* We don't need to copy at this time (it'll get done later) */
5678 return list_nth(context->args, param->paramid - 1);
5679 }
5681}

References substitute_actual_parameters_context::args, elog, ERROR, expression_tree_mutator, fb(), IsA, list_nth(), substitute_actual_parameters_context::nargs, PARAM_EXTERN, Param::paramid, Param::paramkind, substitute_actual_parameters_mutator(), and substitute_actual_parameters_context::usecounts.

Referenced by substitute_actual_parameters(), and substitute_actual_parameters_mutator().

◆ var_is_nonnullable()

bool var_is_nonnullable ( PlannerInfo root,
Var var,
NotNullSource  source 
)

Definition at line 4628 of file clauses.c.

4629{
4630 Assert(IsA(var, Var));
4631
4632 /* skip upper-level Vars */
4633 if (var->varlevelsup != 0)
4634 return false;
4635
4636 /* could the Var be nulled by any outer joins or grouping sets? */
4637 if (!bms_is_empty(var->varnullingrels))
4638 return false;
4639
4640 /*
4641 * If the Var has a non-default returning type, it could be NULL
4642 * regardless of any NOT NULL constraint. For example, OLD.col is NULL
4643 * for INSERT, and NEW.col is NULL for DELETE.
4644 */
4646 return false;
4647
4648 /* system columns cannot be NULL */
4649 if (var->varattno < 0)
4650 return true;
4651
4652 /* we don't trust whole-row Vars */
4653 if (var->varattno == 0)
4654 return false;
4655
4656 /* Check if the Var is defined as NOT NULL. */
4657 switch (source)
4658 {
4660 {
4661 /*
4662 * We retrieve the column NOT NULL constraint information from
4663 * the corresponding RelOptInfo.
4664 */
4665 RelOptInfo *rel;
4666 Bitmapset *notnullattnums;
4667
4668 rel = find_base_rel(root, var->varno);
4669 notnullattnums = rel->notnullattnums;
4670
4671 return bms_is_member(var->varattno, notnullattnums);
4672 }
4674 {
4675 /*
4676 * We retrieve the column NOT NULL constraint information from
4677 * the hash table.
4678 */
4680 Bitmapset *notnullattnums;
4681
4682 rte = planner_rt_fetch(var->varno, root);
4683
4684 /* We can only reason about ordinary relations */
4685 if (rte->rtekind != RTE_RELATION)
4686 return false;
4687
4688 /*
4689 * We must skip inheritance parent tables, as some child
4690 * tables may have a NOT NULL constraint for a column while
4691 * others may not. This cannot happen with partitioned
4692 * tables, though.
4693 */
4694 if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
4695 return false;
4696
4697 notnullattnums = find_relation_notnullatts(root, rte->relid);
4698
4699 return bms_is_member(var->varattno, notnullattnums);
4700 }
4702 {
4703 /*
4704 * We check the attnullability field in the tuple descriptor.
4705 * This is necessary rather than checking the attnotnull field
4706 * from the attribute relation, because attnotnull is also set
4707 * for invalid (NOT VALID) NOT NULL constraints, which do not
4708 * guarantee the absence of NULLs.
4709 */
4711 Relation rel;
4712 CompactAttribute *attr;
4713 bool result;
4714
4715 rte = planner_rt_fetch(var->varno, root);
4716
4717 /* We can only reason about ordinary relations */
4718 if (rte->rtekind != RTE_RELATION)
4719 return false;
4720
4721 /*
4722 * We must skip inheritance parent tables, as some child
4723 * tables may have a NOT NULL constraint for a column while
4724 * others may not. This cannot happen with partitioned
4725 * tables, though.
4726 *
4727 * Note that we need to check if the relation actually has any
4728 * children, as we might not have done that yet.
4729 */
4730 if (rte->inh && has_subclass(rte->relid) &&
4731 rte->relkind != RELKIND_PARTITIONED_TABLE)
4732 return false;
4733
4734 /* We need not lock the relation since it was already locked */
4735 rel = table_open(rte->relid, NoLock);
4737 var->varattno - 1);
4739 table_close(rel, NoLock);
4740
4741 return result;
4742 }
4743 default:
4744 elog(ERROR, "unrecognized NotNullSource: %d",
4745 (int) source);
4746 break;
4747 }
4748
4749 return false;
4750}

References Assert, CompactAttribute::attnullability, ATTNULLABLE_VALID, bms_is_empty, bms_is_member(), elog, ERROR, fb(), find_base_rel(), find_relation_notnullatts(), has_subclass(), IsA, NoLock, NOTNULL_SOURCE_CATALOG, NOTNULL_SOURCE_HASHTABLE, NOTNULL_SOURCE_RELOPT, RelOptInfo::notnullattnums, planner_rt_fetch, RelationGetDescr, result, root, RTE_RELATION, source, table_close(), table_open(), TupleDescCompactAttr(), VAR_RETURNING_DEFAULT, Var::varattno, Var::varlevelsup, Var::varno, and Var::varreturningtype.

Referenced by expr_is_nonnullable().