00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "postgres.h"
00021
00022 #include "access/htup_details.h"
00023 #include "catalog/pg_aggregate.h"
00024 #include "catalog/pg_language.h"
00025 #include "catalog/pg_operator.h"
00026 #include "catalog/pg_proc.h"
00027 #include "catalog/pg_type.h"
00028 #include "executor/executor.h"
00029 #include "executor/functions.h"
00030 #include "funcapi.h"
00031 #include "miscadmin.h"
00032 #include "nodes/makefuncs.h"
00033 #include "nodes/nodeFuncs.h"
00034 #include "optimizer/clauses.h"
00035 #include "optimizer/cost.h"
00036 #include "optimizer/planmain.h"
00037 #include "optimizer/prep.h"
00038 #include "optimizer/var.h"
00039 #include "parser/analyze.h"
00040 #include "parser/parse_coerce.h"
00041 #include "parser/parse_func.h"
00042 #include "rewrite/rewriteManip.h"
00043 #include "tcop/tcopprot.h"
00044 #include "utils/acl.h"
00045 #include "utils/builtins.h"
00046 #include "utils/datum.h"
00047 #include "utils/lsyscache.h"
00048 #include "utils/memutils.h"
00049 #include "utils/syscache.h"
00050 #include "utils/typcache.h"
00051
00052
00053 typedef struct
00054 {
00055 PlannerInfo *root;
00056 AggClauseCosts *costs;
00057 } count_agg_clauses_context;
00058
00059 typedef struct
00060 {
00061 ParamListInfo boundParams;
00062 PlannerInfo *root;
00063 List *active_fns;
00064 Node *case_val;
00065 bool estimate;
00066 } eval_const_expressions_context;
00067
00068 typedef struct
00069 {
00070 int nargs;
00071 List *args;
00072 int *usecounts;
00073 } substitute_actual_parameters_context;
00074
00075 typedef struct
00076 {
00077 int nargs;
00078 List *args;
00079 int sublevels_up;
00080 } substitute_actual_srf_parameters_context;
00081
00082 typedef struct
00083 {
00084 char *proname;
00085 char *prosrc;
00086 } inline_error_callback_arg;
00087
00088 static bool contain_agg_clause_walker(Node *node, void *context);
00089 static bool count_agg_clauses_walker(Node *node,
00090 count_agg_clauses_context *context);
00091 static bool find_window_functions_walker(Node *node, WindowFuncLists *lists);
00092 static bool expression_returns_set_rows_walker(Node *node, double *count);
00093 static bool contain_subplans_walker(Node *node, void *context);
00094 static bool contain_mutable_functions_walker(Node *node, void *context);
00095 static bool contain_volatile_functions_walker(Node *node, void *context);
00096 static bool contain_nonstrict_functions_walker(Node *node, void *context);
00097 static bool contain_leaky_functions_walker(Node *node, void *context);
00098 static Relids find_nonnullable_rels_walker(Node *node, bool top_level);
00099 static List *find_nonnullable_vars_walker(Node *node, bool top_level);
00100 static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK);
00101 static Node *eval_const_expressions_mutator(Node *node,
00102 eval_const_expressions_context *context);
00103 static List *simplify_or_arguments(List *args,
00104 eval_const_expressions_context *context,
00105 bool *haveNull, bool *forceTrue);
00106 static List *simplify_and_arguments(List *args,
00107 eval_const_expressions_context *context,
00108 bool *haveNull, bool *forceFalse);
00109 static Node *simplify_boolean_equality(Oid opno, List *args);
00110 static Expr *simplify_function(Oid funcid,
00111 Oid result_type, int32 result_typmod,
00112 Oid result_collid, Oid input_collid, List **args_p,
00113 bool funcvariadic, bool process_args, bool allow_non_const,
00114 eval_const_expressions_context *context);
00115 static List *expand_function_arguments(List *args, Oid result_type,
00116 HeapTuple func_tuple);
00117 static List *reorder_function_arguments(List *args, HeapTuple func_tuple);
00118 static List *add_function_defaults(List *args, HeapTuple func_tuple);
00119 static List *fetch_function_defaults(HeapTuple func_tuple);
00120 static void recheck_cast_function_args(List *args, Oid result_type,
00121 HeapTuple func_tuple);
00122 static Expr *evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
00123 Oid result_collid, Oid input_collid, List *args,
00124 bool funcvariadic,
00125 HeapTuple func_tuple,
00126 eval_const_expressions_context *context);
00127 static Expr *inline_function(Oid funcid, Oid result_type, Oid result_collid,
00128 Oid input_collid, List *args,
00129 bool funcvariadic,
00130 HeapTuple func_tuple,
00131 eval_const_expressions_context *context);
00132 static Node *substitute_actual_parameters(Node *expr, int nargs, List *args,
00133 int *usecounts);
00134 static Node *substitute_actual_parameters_mutator(Node *node,
00135 substitute_actual_parameters_context *context);
00136 static void sql_inline_error_callback(void *arg);
00137 static Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
00138 Oid result_collation);
00139 static Query *substitute_actual_srf_parameters(Query *expr,
00140 int nargs, List *args);
00141 static Node *substitute_actual_srf_parameters_mutator(Node *node,
00142 substitute_actual_srf_parameters_context *context);
00143 static bool tlist_matches_coltypelist(List *tlist, List *coltypelist);
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 Expr *
00157 make_opclause(Oid opno, Oid opresulttype, bool opretset,
00158 Expr *leftop, Expr *rightop,
00159 Oid opcollid, Oid inputcollid)
00160 {
00161 OpExpr *expr = makeNode(OpExpr);
00162
00163 expr->opno = opno;
00164 expr->opfuncid = InvalidOid;
00165 expr->opresulttype = opresulttype;
00166 expr->opretset = opretset;
00167 expr->opcollid = opcollid;
00168 expr->inputcollid = inputcollid;
00169 if (rightop)
00170 expr->args = list_make2(leftop, rightop);
00171 else
00172 expr->args = list_make1(leftop);
00173 expr->location = -1;
00174 return (Expr *) expr;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 Node *
00184 get_leftop(const Expr *clause)
00185 {
00186 const OpExpr *expr = (const OpExpr *) clause;
00187
00188 if (expr->args != NIL)
00189 return linitial(expr->args);
00190 else
00191 return NULL;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200 Node *
00201 get_rightop(const Expr *clause)
00202 {
00203 const OpExpr *expr = (const OpExpr *) clause;
00204
00205 if (list_length(expr->args) >= 2)
00206 return lsecond(expr->args);
00207 else
00208 return NULL;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 bool
00221 not_clause(Node *clause)
00222 {
00223 return (clause != NULL &&
00224 IsA(clause, BoolExpr) &&
00225 ((BoolExpr *) clause)->boolop == NOT_EXPR);
00226 }
00227
00228
00229
00230
00231
00232
00233 Expr *
00234 make_notclause(Expr *notclause)
00235 {
00236 BoolExpr *expr = makeNode(BoolExpr);
00237
00238 expr->boolop = NOT_EXPR;
00239 expr->args = list_make1(notclause);
00240 expr->location = -1;
00241 return (Expr *) expr;
00242 }
00243
00244
00245
00246
00247
00248
00249 Expr *
00250 get_notclausearg(Expr *notclause)
00251 {
00252 return linitial(((BoolExpr *) notclause)->args);
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 bool
00265 or_clause(Node *clause)
00266 {
00267 return (clause != NULL &&
00268 IsA(clause, BoolExpr) &&
00269 ((BoolExpr *) clause)->boolop == OR_EXPR);
00270 }
00271
00272
00273
00274
00275
00276
00277 Expr *
00278 make_orclause(List *orclauses)
00279 {
00280 BoolExpr *expr = makeNode(BoolExpr);
00281
00282 expr->boolop = OR_EXPR;
00283 expr->args = orclauses;
00284 expr->location = -1;
00285 return (Expr *) expr;
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 bool
00299 and_clause(Node *clause)
00300 {
00301 return (clause != NULL &&
00302 IsA(clause, BoolExpr) &&
00303 ((BoolExpr *) clause)->boolop == AND_EXPR);
00304 }
00305
00306
00307
00308
00309
00310
00311 Expr *
00312 make_andclause(List *andclauses)
00313 {
00314 BoolExpr *expr = makeNode(BoolExpr);
00315
00316 expr->boolop = AND_EXPR;
00317 expr->args = andclauses;
00318 expr->location = -1;
00319 return (Expr *) expr;
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 Node *
00333 make_and_qual(Node *qual1, Node *qual2)
00334 {
00335 if (qual1 == NULL)
00336 return qual2;
00337 if (qual2 == NULL)
00338 return qual1;
00339 return (Node *) make_andclause(list_make2(qual1, qual2));
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 Expr *
00352 make_ands_explicit(List *andclauses)
00353 {
00354 if (andclauses == NIL)
00355 return (Expr *) makeBoolConst(true, false);
00356 else if (list_length(andclauses) == 1)
00357 return (Expr *) linitial(andclauses);
00358 else
00359 return make_andclause(andclauses);
00360 }
00361
00362 List *
00363 make_ands_implicit(Expr *clause)
00364 {
00365
00366
00367
00368
00369
00370
00371 if (clause == NULL)
00372 return NIL;
00373 else if (and_clause((Node *) clause))
00374 return ((BoolExpr *) clause)->args;
00375 else if (IsA(clause, Const) &&
00376 !((Const *) clause)->constisnull &&
00377 DatumGetBool(((Const *) clause)->constvalue))
00378 return NIL;
00379 else
00380 return list_make1(clause);
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 bool
00402 contain_agg_clause(Node *clause)
00403 {
00404 return contain_agg_clause_walker(clause, NULL);
00405 }
00406
00407 static bool
00408 contain_agg_clause_walker(Node *node, void *context)
00409 {
00410 if (node == NULL)
00411 return false;
00412 if (IsA(node, Aggref))
00413 {
00414 Assert(((Aggref *) node)->agglevelsup == 0);
00415 return true;
00416 }
00417 Assert(!IsA(node, SubLink));
00418 return expression_tree_walker(node, contain_agg_clause_walker, context);
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 void
00441 count_agg_clauses(PlannerInfo *root, Node *clause, AggClauseCosts *costs)
00442 {
00443 count_agg_clauses_context context;
00444
00445 context.root = root;
00446 context.costs = costs;
00447 (void) count_agg_clauses_walker(clause, &context);
00448 }
00449
00450 static bool
00451 count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
00452 {
00453 if (node == NULL)
00454 return false;
00455 if (IsA(node, Aggref))
00456 {
00457 Aggref *aggref = (Aggref *) node;
00458 AggClauseCosts *costs = context->costs;
00459 HeapTuple aggTuple;
00460 Form_pg_aggregate aggform;
00461 Oid aggtransfn;
00462 Oid aggfinalfn;
00463 Oid aggtranstype;
00464 QualCost argcosts;
00465 Oid *inputTypes;
00466 int numArguments;
00467 ListCell *l;
00468
00469 Assert(aggref->agglevelsup == 0);
00470
00471
00472 aggTuple = SearchSysCache1(AGGFNOID,
00473 ObjectIdGetDatum(aggref->aggfnoid));
00474 if (!HeapTupleIsValid(aggTuple))
00475 elog(ERROR, "cache lookup failed for aggregate %u",
00476 aggref->aggfnoid);
00477 aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
00478 aggtransfn = aggform->aggtransfn;
00479 aggfinalfn = aggform->aggfinalfn;
00480 aggtranstype = aggform->aggtranstype;
00481 ReleaseSysCache(aggTuple);
00482
00483
00484 costs->numAggs++;
00485 if (aggref->aggorder != NIL || aggref->aggdistinct != NIL)
00486 costs->numOrderedAggs++;
00487
00488
00489 costs->transCost.per_tuple += get_func_cost(aggtransfn) * cpu_operator_cost;
00490 if (OidIsValid(aggfinalfn))
00491 costs->finalCost += get_func_cost(aggfinalfn) * cpu_operator_cost;
00492
00493
00494 cost_qual_eval_node(&argcosts, (Node *) aggref->args, context->root);
00495 costs->transCost.startup += argcosts.startup;
00496 costs->transCost.per_tuple += argcosts.per_tuple;
00497
00498
00499 inputTypes = (Oid *) palloc(sizeof(Oid) * list_length(aggref->args));
00500 numArguments = 0;
00501 foreach(l, aggref->args)
00502 {
00503 TargetEntry *tle = (TargetEntry *) lfirst(l);
00504
00505 if (!tle->resjunk)
00506 inputTypes[numArguments++] = exprType((Node *) tle->expr);
00507 }
00508
00509
00510 if (IsPolymorphicType(aggtranstype))
00511 {
00512
00513 Oid *declaredArgTypes;
00514 int agg_nargs;
00515
00516 (void) get_func_signature(aggref->aggfnoid,
00517 &declaredArgTypes, &agg_nargs);
00518 Assert(agg_nargs == numArguments);
00519 aggtranstype = enforce_generic_type_consistency(inputTypes,
00520 declaredArgTypes,
00521 agg_nargs,
00522 aggtranstype,
00523 false);
00524 pfree(declaredArgTypes);
00525 }
00526
00527
00528
00529
00530
00531
00532
00533 if (!get_typbyval(aggtranstype))
00534 {
00535 int32 aggtranstypmod;
00536 int32 avgwidth;
00537
00538
00539
00540
00541
00542
00543 if (numArguments > 0 && aggtranstype == inputTypes[0])
00544 aggtranstypmod = exprTypmod((Node *) linitial(aggref->args));
00545 else
00546 aggtranstypmod = -1;
00547
00548 avgwidth = get_typavgwidth(aggtranstype, aggtranstypmod);
00549 avgwidth = MAXALIGN(avgwidth);
00550
00551 costs->transitionSpace += avgwidth + 2 * sizeof(void *);
00552 }
00553 else if (aggtranstype == INTERNALOID)
00554 {
00555
00556
00557
00558
00559
00560
00561
00562
00563 costs->transitionSpace += ALLOCSET_DEFAULT_INITSIZE;
00564 }
00565
00566
00567
00568
00569
00570 if (contain_agg_clause((Node *) aggref->args))
00571 ereport(ERROR,
00572 (errcode(ERRCODE_GROUPING_ERROR),
00573 errmsg("aggregate function calls cannot be nested")));
00574
00575
00576
00577
00578 return false;
00579 }
00580 Assert(!IsA(node, SubLink));
00581 return expression_tree_walker(node, count_agg_clauses_walker,
00582 (void *) context);
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 bool
00599 contain_window_function(Node *clause)
00600 {
00601 return contain_windowfuncs(clause);
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611 WindowFuncLists *
00612 find_window_functions(Node *clause, Index maxWinRef)
00613 {
00614 WindowFuncLists *lists = palloc(sizeof(WindowFuncLists));
00615
00616 lists->numWindowFuncs = 0;
00617 lists->maxWinRef = maxWinRef;
00618 lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
00619 (void) find_window_functions_walker(clause, lists);
00620 return lists;
00621 }
00622
00623 static bool
00624 find_window_functions_walker(Node *node, WindowFuncLists *lists)
00625 {
00626 if (node == NULL)
00627 return false;
00628 if (IsA(node, WindowFunc))
00629 {
00630 WindowFunc *wfunc = (WindowFunc *) node;
00631
00632
00633 if (wfunc->winref > lists->maxWinRef)
00634 elog(ERROR, "WindowFunc contains out-of-range winref %u",
00635 wfunc->winref);
00636 lists->windowFuncs[wfunc->winref] =
00637 lappend(lists->windowFuncs[wfunc->winref], wfunc);
00638 lists->numWindowFuncs++;
00639
00640
00641
00642
00643
00644 if (contain_window_function((Node *) wfunc->args))
00645 ereport(ERROR,
00646 (errcode(ERRCODE_WINDOWING_ERROR),
00647 errmsg("window function calls cannot be nested")));
00648
00649
00650
00651
00652 return false;
00653 }
00654 Assert(!IsA(node, SubLink));
00655 return expression_tree_walker(node, find_window_functions_walker,
00656 (void *) lists);
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675 double
00676 expression_returns_set_rows(Node *clause)
00677 {
00678 double result = 1;
00679
00680 (void) expression_returns_set_rows_walker(clause, &result);
00681 return clamp_row_est(result);
00682 }
00683
00684 static bool
00685 expression_returns_set_rows_walker(Node *node, double *count)
00686 {
00687 if (node == NULL)
00688 return false;
00689 if (IsA(node, FuncExpr))
00690 {
00691 FuncExpr *expr = (FuncExpr *) node;
00692
00693 if (expr->funcretset)
00694 *count *= get_func_rows(expr->funcid);
00695 }
00696 if (IsA(node, OpExpr))
00697 {
00698 OpExpr *expr = (OpExpr *) node;
00699
00700 if (expr->opretset)
00701 {
00702 set_opfuncid(expr);
00703 *count *= get_func_rows(expr->opfuncid);
00704 }
00705 }
00706
00707
00708 if (IsA(node, Aggref))
00709 return false;
00710 if (IsA(node, WindowFunc))
00711 return false;
00712 if (IsA(node, DistinctExpr))
00713 return false;
00714 if (IsA(node, NullIfExpr))
00715 return false;
00716 if (IsA(node, ScalarArrayOpExpr))
00717 return false;
00718 if (IsA(node, BoolExpr))
00719 return false;
00720 if (IsA(node, SubLink))
00721 return false;
00722 if (IsA(node, SubPlan))
00723 return false;
00724 if (IsA(node, AlternativeSubPlan))
00725 return false;
00726 if (IsA(node, ArrayExpr))
00727 return false;
00728 if (IsA(node, RowExpr))
00729 return false;
00730 if (IsA(node, RowCompareExpr))
00731 return false;
00732 if (IsA(node, CoalesceExpr))
00733 return false;
00734 if (IsA(node, MinMaxExpr))
00735 return false;
00736 if (IsA(node, XmlExpr))
00737 return false;
00738
00739 return expression_tree_walker(node, expression_returns_set_rows_walker,
00740 (void *) count);
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 double
00760 tlist_returns_set_rows(List *tlist)
00761 {
00762 double result = 1;
00763 ListCell *lc;
00764
00765 foreach(lc, tlist)
00766 {
00767 TargetEntry *tle = (TargetEntry *) lfirst(lc);
00768 double colresult;
00769
00770 colresult = expression_returns_set_rows((Node *) tle->expr);
00771 if (result < colresult)
00772 result = colresult;
00773 }
00774 return result;
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 bool
00794 contain_subplans(Node *clause)
00795 {
00796 return contain_subplans_walker(clause, NULL);
00797 }
00798
00799 static bool
00800 contain_subplans_walker(Node *node, void *context)
00801 {
00802 if (node == NULL)
00803 return false;
00804 if (IsA(node, SubPlan) ||
00805 IsA(node, AlternativeSubPlan) ||
00806 IsA(node, SubLink))
00807 return true;
00808 return expression_tree_walker(node, contain_subplans_walker, context);
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 bool
00829 contain_mutable_functions(Node *clause)
00830 {
00831 return contain_mutable_functions_walker(clause, NULL);
00832 }
00833
00834 static bool
00835 contain_mutable_functions_walker(Node *node, void *context)
00836 {
00837 if (node == NULL)
00838 return false;
00839 if (IsA(node, FuncExpr))
00840 {
00841 FuncExpr *expr = (FuncExpr *) node;
00842
00843 if (func_volatile(expr->funcid) != PROVOLATILE_IMMUTABLE)
00844 return true;
00845
00846 }
00847 else if (IsA(node, OpExpr))
00848 {
00849 OpExpr *expr = (OpExpr *) node;
00850
00851 set_opfuncid(expr);
00852 if (func_volatile(expr->opfuncid) != PROVOLATILE_IMMUTABLE)
00853 return true;
00854
00855 }
00856 else if (IsA(node, DistinctExpr))
00857 {
00858 DistinctExpr *expr = (DistinctExpr *) node;
00859
00860 set_opfuncid((OpExpr *) expr);
00861 if (func_volatile(expr->opfuncid) != PROVOLATILE_IMMUTABLE)
00862 return true;
00863
00864 }
00865 else if (IsA(node, NullIfExpr))
00866 {
00867 NullIfExpr *expr = (NullIfExpr *) node;
00868
00869 set_opfuncid((OpExpr *) expr);
00870 if (func_volatile(expr->opfuncid) != PROVOLATILE_IMMUTABLE)
00871 return true;
00872
00873 }
00874 else if (IsA(node, ScalarArrayOpExpr))
00875 {
00876 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
00877
00878 set_sa_opfuncid(expr);
00879 if (func_volatile(expr->opfuncid) != PROVOLATILE_IMMUTABLE)
00880 return true;
00881
00882 }
00883 else if (IsA(node, CoerceViaIO))
00884 {
00885 CoerceViaIO *expr = (CoerceViaIO *) node;
00886 Oid iofunc;
00887 Oid typioparam;
00888 bool typisvarlena;
00889
00890
00891 getTypeInputInfo(expr->resulttype,
00892 &iofunc, &typioparam);
00893 if (func_volatile(iofunc) != PROVOLATILE_IMMUTABLE)
00894 return true;
00895
00896 getTypeOutputInfo(exprType((Node *) expr->arg),
00897 &iofunc, &typisvarlena);
00898 if (func_volatile(iofunc) != PROVOLATILE_IMMUTABLE)
00899 return true;
00900
00901 }
00902 else if (IsA(node, ArrayCoerceExpr))
00903 {
00904 ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
00905
00906 if (OidIsValid(expr->elemfuncid) &&
00907 func_volatile(expr->elemfuncid) != PROVOLATILE_IMMUTABLE)
00908 return true;
00909
00910 }
00911 else if (IsA(node, RowCompareExpr))
00912 {
00913 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
00914 ListCell *opid;
00915
00916 foreach(opid, rcexpr->opnos)
00917 {
00918 if (op_volatile(lfirst_oid(opid)) != PROVOLATILE_IMMUTABLE)
00919 return true;
00920 }
00921
00922 }
00923 return expression_tree_walker(node, contain_mutable_functions_walker,
00924 context);
00925 }
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 bool
00944 contain_volatile_functions(Node *clause)
00945 {
00946 return contain_volatile_functions_walker(clause, NULL);
00947 }
00948
00949 static bool
00950 contain_volatile_functions_walker(Node *node, void *context)
00951 {
00952 if (node == NULL)
00953 return false;
00954 if (IsA(node, FuncExpr))
00955 {
00956 FuncExpr *expr = (FuncExpr *) node;
00957
00958 if (func_volatile(expr->funcid) == PROVOLATILE_VOLATILE)
00959 return true;
00960
00961 }
00962 else if (IsA(node, OpExpr))
00963 {
00964 OpExpr *expr = (OpExpr *) node;
00965
00966 set_opfuncid(expr);
00967 if (func_volatile(expr->opfuncid) == PROVOLATILE_VOLATILE)
00968 return true;
00969
00970 }
00971 else if (IsA(node, DistinctExpr))
00972 {
00973 DistinctExpr *expr = (DistinctExpr *) node;
00974
00975 set_opfuncid((OpExpr *) expr);
00976 if (func_volatile(expr->opfuncid) == PROVOLATILE_VOLATILE)
00977 return true;
00978
00979 }
00980 else if (IsA(node, NullIfExpr))
00981 {
00982 NullIfExpr *expr = (NullIfExpr *) node;
00983
00984 set_opfuncid((OpExpr *) expr);
00985 if (func_volatile(expr->opfuncid) == PROVOLATILE_VOLATILE)
00986 return true;
00987
00988 }
00989 else if (IsA(node, ScalarArrayOpExpr))
00990 {
00991 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
00992
00993 set_sa_opfuncid(expr);
00994 if (func_volatile(expr->opfuncid) == PROVOLATILE_VOLATILE)
00995 return true;
00996
00997 }
00998 else if (IsA(node, CoerceViaIO))
00999 {
01000 CoerceViaIO *expr = (CoerceViaIO *) node;
01001 Oid iofunc;
01002 Oid typioparam;
01003 bool typisvarlena;
01004
01005
01006 getTypeInputInfo(expr->resulttype,
01007 &iofunc, &typioparam);
01008 if (func_volatile(iofunc) == PROVOLATILE_VOLATILE)
01009 return true;
01010
01011 getTypeOutputInfo(exprType((Node *) expr->arg),
01012 &iofunc, &typisvarlena);
01013 if (func_volatile(iofunc) == PROVOLATILE_VOLATILE)
01014 return true;
01015
01016 }
01017 else if (IsA(node, ArrayCoerceExpr))
01018 {
01019 ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
01020
01021 if (OidIsValid(expr->elemfuncid) &&
01022 func_volatile(expr->elemfuncid) == PROVOLATILE_VOLATILE)
01023 return true;
01024
01025 }
01026 else if (IsA(node, RowCompareExpr))
01027 {
01028
01029 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
01030 ListCell *opid;
01031
01032 foreach(opid, rcexpr->opnos)
01033 {
01034 if (op_volatile(lfirst_oid(opid)) == PROVOLATILE_VOLATILE)
01035 return true;
01036 }
01037
01038 }
01039 return expression_tree_walker(node, contain_volatile_functions_walker,
01040 context);
01041 }
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 bool
01061 contain_nonstrict_functions(Node *clause)
01062 {
01063 return contain_nonstrict_functions_walker(clause, NULL);
01064 }
01065
01066 static bool
01067 contain_nonstrict_functions_walker(Node *node, void *context)
01068 {
01069 if (node == NULL)
01070 return false;
01071 if (IsA(node, Aggref))
01072 {
01073
01074 return true;
01075 }
01076 if (IsA(node, WindowFunc))
01077 {
01078
01079 return true;
01080 }
01081 if (IsA(node, ArrayRef))
01082 {
01083
01084 if (((ArrayRef *) node)->refassgnexpr != NULL)
01085 return true;
01086
01087 }
01088 if (IsA(node, FuncExpr))
01089 {
01090 FuncExpr *expr = (FuncExpr *) node;
01091
01092 if (!func_strict(expr->funcid))
01093 return true;
01094
01095 }
01096 if (IsA(node, OpExpr))
01097 {
01098 OpExpr *expr = (OpExpr *) node;
01099
01100 set_opfuncid(expr);
01101 if (!func_strict(expr->opfuncid))
01102 return true;
01103
01104 }
01105 if (IsA(node, DistinctExpr))
01106 {
01107
01108 return true;
01109 }
01110 if (IsA(node, NullIfExpr))
01111 return true;
01112 if (IsA(node, ScalarArrayOpExpr))
01113 {
01114 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
01115
01116 if (!is_strict_saop(expr, false))
01117 return true;
01118
01119 }
01120 if (IsA(node, BoolExpr))
01121 {
01122 BoolExpr *expr = (BoolExpr *) node;
01123
01124 switch (expr->boolop)
01125 {
01126 case AND_EXPR:
01127 case OR_EXPR:
01128
01129 return true;
01130 default:
01131 break;
01132 }
01133 }
01134 if (IsA(node, SubLink))
01135 {
01136
01137 return true;
01138 }
01139 if (IsA(node, SubPlan))
01140 return true;
01141 if (IsA(node, AlternativeSubPlan))
01142 return true;
01143
01144 if (IsA(node, FieldStore))
01145 return true;
01146 if (IsA(node, CaseExpr))
01147 return true;
01148 if (IsA(node, ArrayExpr))
01149 return true;
01150 if (IsA(node, RowExpr))
01151 return true;
01152 if (IsA(node, RowCompareExpr))
01153 return true;
01154 if (IsA(node, CoalesceExpr))
01155 return true;
01156 if (IsA(node, MinMaxExpr))
01157 return true;
01158 if (IsA(node, XmlExpr))
01159 return true;
01160 if (IsA(node, NullTest))
01161 return true;
01162 if (IsA(node, BooleanTest))
01163 return true;
01164 return expression_tree_walker(node, contain_nonstrict_functions_walker,
01165 context);
01166 }
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 bool
01182 contain_leaky_functions(Node *clause)
01183 {
01184 return contain_leaky_functions_walker(clause, NULL);
01185 }
01186
01187 static bool
01188 contain_leaky_functions_walker(Node *node, void *context)
01189 {
01190 if (node == NULL)
01191 return false;
01192
01193 switch (nodeTag(node))
01194 {
01195 case T_Var:
01196 case T_Const:
01197 case T_Param:
01198 case T_ArrayExpr:
01199 case T_NamedArgExpr:
01200 case T_BoolExpr:
01201 case T_RelabelType:
01202 case T_CaseExpr:
01203 case T_CaseTestExpr:
01204 case T_RowExpr:
01205 case T_MinMaxExpr:
01206 case T_NullTest:
01207 case T_BooleanTest:
01208 case T_List:
01209
01210
01211
01212
01213
01214 break;
01215
01216 case T_FuncExpr:
01217 {
01218 FuncExpr *expr = (FuncExpr *) node;
01219
01220 if (!get_func_leakproof(expr->funcid))
01221 return true;
01222 }
01223 break;
01224
01225 case T_OpExpr:
01226 case T_DistinctExpr:
01227 case T_NullIfExpr:
01228 {
01229 OpExpr *expr = (OpExpr *) node;
01230
01231 set_opfuncid(expr);
01232 if (!get_func_leakproof(expr->opfuncid))
01233 return true;
01234 }
01235 break;
01236
01237 case T_ScalarArrayOpExpr:
01238 {
01239 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
01240
01241 set_sa_opfuncid(expr);
01242 if (!get_func_leakproof(expr->opfuncid))
01243 return true;
01244 }
01245 break;
01246
01247 case T_CoerceViaIO:
01248 {
01249 CoerceViaIO *expr = (CoerceViaIO *) node;
01250 Oid funcid;
01251 Oid ioparam;
01252 bool varlena;
01253
01254 getTypeInputInfo(exprType((Node *) expr->arg),
01255 &funcid, &ioparam);
01256 if (!get_func_leakproof(funcid))
01257 return true;
01258
01259 getTypeOutputInfo(expr->resulttype, &funcid, &varlena);
01260 if (!get_func_leakproof(funcid))
01261 return true;
01262 }
01263 break;
01264
01265 case T_ArrayCoerceExpr:
01266 {
01267 ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
01268 Oid funcid;
01269 Oid ioparam;
01270 bool varlena;
01271
01272 getTypeInputInfo(exprType((Node *) expr->arg),
01273 &funcid, &ioparam);
01274 if (!get_func_leakproof(funcid))
01275 return true;
01276 getTypeOutputInfo(expr->resulttype, &funcid, &varlena);
01277 if (!get_func_leakproof(funcid))
01278 return true;
01279 }
01280 break;
01281
01282 case T_RowCompareExpr:
01283 {
01284 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
01285 ListCell *opid;
01286
01287 foreach(opid, rcexpr->opnos)
01288 {
01289 Oid funcid = get_opcode(lfirst_oid(opid));
01290
01291 if (!get_func_leakproof(funcid))
01292 return true;
01293 }
01294 }
01295 break;
01296
01297 default:
01298
01299
01300
01301
01302
01303
01304 return true;
01305 }
01306 return expression_tree_walker(node, contain_leaky_functions_walker,
01307 context);
01308 }
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341 Relids
01342 find_nonnullable_rels(Node *clause)
01343 {
01344 return find_nonnullable_rels_walker(clause, true);
01345 }
01346
01347 static Relids
01348 find_nonnullable_rels_walker(Node *node, bool top_level)
01349 {
01350 Relids result = NULL;
01351 ListCell *l;
01352
01353 if (node == NULL)
01354 return NULL;
01355 if (IsA(node, Var))
01356 {
01357 Var *var = (Var *) node;
01358
01359 if (var->varlevelsup == 0)
01360 result = bms_make_singleton(var->varno);
01361 }
01362 else if (IsA(node, List))
01363 {
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373 foreach(l, (List *) node)
01374 {
01375 result = bms_join(result,
01376 find_nonnullable_rels_walker(lfirst(l),
01377 top_level));
01378 }
01379 }
01380 else if (IsA(node, FuncExpr))
01381 {
01382 FuncExpr *expr = (FuncExpr *) node;
01383
01384 if (func_strict(expr->funcid))
01385 result = find_nonnullable_rels_walker((Node *) expr->args, false);
01386 }
01387 else if (IsA(node, OpExpr))
01388 {
01389 OpExpr *expr = (OpExpr *) node;
01390
01391 set_opfuncid(expr);
01392 if (func_strict(expr->opfuncid))
01393 result = find_nonnullable_rels_walker((Node *) expr->args, false);
01394 }
01395 else if (IsA(node, ScalarArrayOpExpr))
01396 {
01397 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
01398
01399 if (is_strict_saop(expr, true))
01400 result = find_nonnullable_rels_walker((Node *) expr->args, false);
01401 }
01402 else if (IsA(node, BoolExpr))
01403 {
01404 BoolExpr *expr = (BoolExpr *) node;
01405
01406 switch (expr->boolop)
01407 {
01408 case AND_EXPR:
01409
01410 if (top_level)
01411 {
01412 result = find_nonnullable_rels_walker((Node *) expr->args,
01413 top_level);
01414 break;
01415 }
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 case OR_EXPR:
01426
01427
01428
01429
01430
01431
01432 foreach(l, expr->args)
01433 {
01434 Relids subresult;
01435
01436 subresult = find_nonnullable_rels_walker(lfirst(l),
01437 top_level);
01438 if (result == NULL)
01439 result = subresult;
01440 else
01441 result = bms_int_members(result, subresult);
01442
01443
01444
01445
01446
01447 if (bms_is_empty(result))
01448 break;
01449 }
01450 break;
01451 case NOT_EXPR:
01452
01453 result = find_nonnullable_rels_walker((Node *) expr->args,
01454 false);
01455 break;
01456 default:
01457 elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
01458 break;
01459 }
01460 }
01461 else if (IsA(node, RelabelType))
01462 {
01463 RelabelType *expr = (RelabelType *) node;
01464
01465 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
01466 }
01467 else if (IsA(node, CoerceViaIO))
01468 {
01469
01470 CoerceViaIO *expr = (CoerceViaIO *) node;
01471
01472 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
01473 }
01474 else if (IsA(node, ArrayCoerceExpr))
01475 {
01476
01477 ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
01478
01479 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
01480 }
01481 else if (IsA(node, ConvertRowtypeExpr))
01482 {
01483
01484 ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
01485
01486 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
01487 }
01488 else if (IsA(node, CollateExpr))
01489 {
01490 CollateExpr *expr = (CollateExpr *) node;
01491
01492 result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
01493 }
01494 else if (IsA(node, NullTest))
01495 {
01496
01497 NullTest *expr = (NullTest *) node;
01498
01499 if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
01500 result = find_nonnullable_rels_walker((Node *) expr->arg, false);
01501 }
01502 else if (IsA(node, BooleanTest))
01503 {
01504
01505 BooleanTest *expr = (BooleanTest *) node;
01506
01507 if (top_level &&
01508 (expr->booltesttype == IS_TRUE ||
01509 expr->booltesttype == IS_FALSE ||
01510 expr->booltesttype == IS_NOT_UNKNOWN))
01511 result = find_nonnullable_rels_walker((Node *) expr->arg, false);
01512 }
01513 else if (IsA(node, PlaceHolderVar))
01514 {
01515 PlaceHolderVar *phv = (PlaceHolderVar *) node;
01516
01517 result = find_nonnullable_rels_walker((Node *) phv->phexpr, top_level);
01518 }
01519 return result;
01520 }
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549 List *
01550 find_nonnullable_vars(Node *clause)
01551 {
01552 return find_nonnullable_vars_walker(clause, true);
01553 }
01554
01555 static List *
01556 find_nonnullable_vars_walker(Node *node, bool top_level)
01557 {
01558 List *result = NIL;
01559 ListCell *l;
01560
01561 if (node == NULL)
01562 return NIL;
01563 if (IsA(node, Var))
01564 {
01565 Var *var = (Var *) node;
01566
01567 if (var->varlevelsup == 0)
01568 result = list_make1(var);
01569 }
01570 else if (IsA(node, List))
01571 {
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581 foreach(l, (List *) node)
01582 {
01583 result = list_concat(result,
01584 find_nonnullable_vars_walker(lfirst(l),
01585 top_level));
01586 }
01587 }
01588 else if (IsA(node, FuncExpr))
01589 {
01590 FuncExpr *expr = (FuncExpr *) node;
01591
01592 if (func_strict(expr->funcid))
01593 result = find_nonnullable_vars_walker((Node *) expr->args, false);
01594 }
01595 else if (IsA(node, OpExpr))
01596 {
01597 OpExpr *expr = (OpExpr *) node;
01598
01599 set_opfuncid(expr);
01600 if (func_strict(expr->opfuncid))
01601 result = find_nonnullable_vars_walker((Node *) expr->args, false);
01602 }
01603 else if (IsA(node, ScalarArrayOpExpr))
01604 {
01605 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
01606
01607 if (is_strict_saop(expr, true))
01608 result = find_nonnullable_vars_walker((Node *) expr->args, false);
01609 }
01610 else if (IsA(node, BoolExpr))
01611 {
01612 BoolExpr *expr = (BoolExpr *) node;
01613
01614 switch (expr->boolop)
01615 {
01616 case AND_EXPR:
01617
01618 if (top_level)
01619 {
01620 result = find_nonnullable_vars_walker((Node *) expr->args,
01621 top_level);
01622 break;
01623 }
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633 case OR_EXPR:
01634
01635
01636
01637
01638
01639
01640 foreach(l, expr->args)
01641 {
01642 List *subresult;
01643
01644 subresult = find_nonnullable_vars_walker(lfirst(l),
01645 top_level);
01646 if (result == NIL)
01647 result = subresult;
01648 else
01649 result = list_intersection(result, subresult);
01650
01651
01652
01653
01654
01655 if (result == NIL)
01656 break;
01657 }
01658 break;
01659 case NOT_EXPR:
01660
01661 result = find_nonnullable_vars_walker((Node *) expr->args,
01662 false);
01663 break;
01664 default:
01665 elog(ERROR, "unrecognized boolop: %d", (int) expr->boolop);
01666 break;
01667 }
01668 }
01669 else if (IsA(node, RelabelType))
01670 {
01671 RelabelType *expr = (RelabelType *) node;
01672
01673 result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
01674 }
01675 else if (IsA(node, CoerceViaIO))
01676 {
01677
01678 CoerceViaIO *expr = (CoerceViaIO *) node;
01679
01680 result = find_nonnullable_vars_walker((Node *) expr->arg, false);
01681 }
01682 else if (IsA(node, ArrayCoerceExpr))
01683 {
01684
01685 ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
01686
01687 result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
01688 }
01689 else if (IsA(node, ConvertRowtypeExpr))
01690 {
01691
01692 ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
01693
01694 result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
01695 }
01696 else if (IsA(node, CollateExpr))
01697 {
01698 CollateExpr *expr = (CollateExpr *) node;
01699
01700 result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
01701 }
01702 else if (IsA(node, NullTest))
01703 {
01704
01705 NullTest *expr = (NullTest *) node;
01706
01707 if (top_level && expr->nulltesttype == IS_NOT_NULL && !expr->argisrow)
01708 result = find_nonnullable_vars_walker((Node *) expr->arg, false);
01709 }
01710 else if (IsA(node, BooleanTest))
01711 {
01712
01713 BooleanTest *expr = (BooleanTest *) node;
01714
01715 if (top_level &&
01716 (expr->booltesttype == IS_TRUE ||
01717 expr->booltesttype == IS_FALSE ||
01718 expr->booltesttype == IS_NOT_UNKNOWN))
01719 result = find_nonnullable_vars_walker((Node *) expr->arg, false);
01720 }
01721 else if (IsA(node, PlaceHolderVar))
01722 {
01723 PlaceHolderVar *phv = (PlaceHolderVar *) node;
01724
01725 result = find_nonnullable_vars_walker((Node *) phv->phexpr, top_level);
01726 }
01727 return result;
01728 }
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742 List *
01743 find_forced_null_vars(Node *node)
01744 {
01745 List *result = NIL;
01746 Var *var;
01747 ListCell *l;
01748
01749 if (node == NULL)
01750 return NIL;
01751
01752 var = find_forced_null_var(node);
01753 if (var)
01754 {
01755 result = list_make1(var);
01756 }
01757
01758 else if (IsA(node, List))
01759 {
01760
01761
01762
01763
01764 foreach(l, (List *) node)
01765 {
01766 result = list_concat(result,
01767 find_forced_null_vars(lfirst(l)));
01768 }
01769 }
01770 else if (IsA(node, BoolExpr))
01771 {
01772 BoolExpr *expr = (BoolExpr *) node;
01773
01774
01775
01776
01777
01778
01779 if (expr->boolop == AND_EXPR)
01780 {
01781
01782 result = find_forced_null_vars((Node *) expr->args);
01783 }
01784 }
01785 return result;
01786 }
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801 Var *
01802 find_forced_null_var(Node *node)
01803 {
01804 if (node == NULL)
01805 return NULL;
01806 if (IsA(node, NullTest))
01807 {
01808
01809 NullTest *expr = (NullTest *) node;
01810
01811 if (expr->nulltesttype == IS_NULL && !expr->argisrow)
01812 {
01813 Var *var = (Var *) expr->arg;
01814
01815 if (var && IsA(var, Var) &&
01816 var->varlevelsup == 0)
01817 return var;
01818 }
01819 }
01820 else if (IsA(node, BooleanTest))
01821 {
01822
01823 BooleanTest *expr = (BooleanTest *) node;
01824
01825 if (expr->booltesttype == IS_UNKNOWN)
01826 {
01827 Var *var = (Var *) expr->arg;
01828
01829 if (var && IsA(var, Var) &&
01830 var->varlevelsup == 0)
01831 return var;
01832 }
01833 }
01834 return NULL;
01835 }
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850 static bool
01851 is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
01852 {
01853 Node *rightop;
01854
01855
01856 set_sa_opfuncid(expr);
01857 if (!func_strict(expr->opfuncid))
01858 return false;
01859
01860 if (expr->useOr && falseOK)
01861 return true;
01862
01863 Assert(list_length(expr->args) == 2);
01864 rightop = (Node *) lsecond(expr->args);
01865 if (rightop && IsA(rightop, Const))
01866 {
01867 Datum arraydatum = ((Const *) rightop)->constvalue;
01868 bool arrayisnull = ((Const *) rightop)->constisnull;
01869 ArrayType *arrayval;
01870 int nitems;
01871
01872 if (arrayisnull)
01873 return false;
01874 arrayval = DatumGetArrayTypeP(arraydatum);
01875 nitems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval));
01876 if (nitems > 0)
01877 return true;
01878 }
01879 else if (rightop && IsA(rightop, ArrayExpr))
01880 {
01881 ArrayExpr *arrayexpr = (ArrayExpr *) rightop;
01882
01883 if (arrayexpr->elements != NIL && !arrayexpr->multidims)
01884 return true;
01885 }
01886 return false;
01887 }
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911 bool
01912 is_pseudo_constant_clause(Node *clause)
01913 {
01914
01915
01916
01917
01918
01919
01920 if (!contain_var_clause(clause) &&
01921 !contain_volatile_functions(clause))
01922 return true;
01923 return false;
01924 }
01925
01926
01927
01928
01929
01930
01931 bool
01932 is_pseudo_constant_clause_relids(Node *clause, Relids relids)
01933 {
01934 if (bms_is_empty(relids) &&
01935 !contain_volatile_functions(clause))
01936 return true;
01937 return false;
01938 }
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953 int
01954 NumRelids(Node *clause)
01955 {
01956 Relids varnos = pull_varnos(clause);
01957 int result = bms_num_members(varnos);
01958
01959 bms_free(varnos);
01960 return result;
01961 }
01962
01963
01964
01965
01966
01967
01968 void
01969 CommuteOpExpr(OpExpr *clause)
01970 {
01971 Oid opoid;
01972 Node *temp;
01973
01974
01975 if (!is_opclause(clause) ||
01976 list_length(clause->args) != 2)
01977 elog(ERROR, "cannot commute non-binary-operator clause");
01978
01979 opoid = get_commutator(clause->opno);
01980
01981 if (!OidIsValid(opoid))
01982 elog(ERROR, "could not find commutator for operator %u",
01983 clause->opno);
01984
01985
01986
01987
01988 clause->opno = opoid;
01989 clause->opfuncid = InvalidOid;
01990
01991
01992 temp = linitial(clause->args);
01993 linitial(clause->args) = lsecond(clause->args);
01994 lsecond(clause->args) = temp;
01995 }
01996
01997
01998
01999
02000
02001
02002 void
02003 CommuteRowCompareExpr(RowCompareExpr *clause)
02004 {
02005 List *newops;
02006 List *temp;
02007 ListCell *l;
02008
02009
02010 if (!IsA(clause, RowCompareExpr))
02011 elog(ERROR, "expected a RowCompareExpr");
02012
02013
02014 newops = NIL;
02015 foreach(l, clause->opnos)
02016 {
02017 Oid opoid = lfirst_oid(l);
02018
02019 opoid = get_commutator(opoid);
02020 if (!OidIsValid(opoid))
02021 elog(ERROR, "could not find commutator for operator %u",
02022 lfirst_oid(l));
02023 newops = lappend_oid(newops, opoid);
02024 }
02025
02026
02027
02028
02029 switch (clause->rctype)
02030 {
02031 case ROWCOMPARE_LT:
02032 clause->rctype = ROWCOMPARE_GT;
02033 break;
02034 case ROWCOMPARE_LE:
02035 clause->rctype = ROWCOMPARE_GE;
02036 break;
02037 case ROWCOMPARE_GE:
02038 clause->rctype = ROWCOMPARE_LE;
02039 break;
02040 case ROWCOMPARE_GT:
02041 clause->rctype = ROWCOMPARE_LT;
02042 break;
02043 default:
02044 elog(ERROR, "unexpected RowCompare type: %d",
02045 (int) clause->rctype);
02046 break;
02047 }
02048
02049 clause->opnos = newops;
02050
02051
02052
02053
02054
02055
02056
02057 temp = clause->largs;
02058 clause->largs = clause->rargs;
02059 clause->rargs = temp;
02060 }
02061
02062
02063
02064
02065
02066
02067
02068 Node *
02069 strip_implicit_coercions(Node *node)
02070 {
02071 if (node == NULL)
02072 return NULL;
02073 if (IsA(node, FuncExpr))
02074 {
02075 FuncExpr *f = (FuncExpr *) node;
02076
02077 if (f->funcformat == COERCE_IMPLICIT_CAST)
02078 return strip_implicit_coercions(linitial(f->args));
02079 }
02080 else if (IsA(node, RelabelType))
02081 {
02082 RelabelType *r = (RelabelType *) node;
02083
02084 if (r->relabelformat == COERCE_IMPLICIT_CAST)
02085 return strip_implicit_coercions((Node *) r->arg);
02086 }
02087 else if (IsA(node, CoerceViaIO))
02088 {
02089 CoerceViaIO *c = (CoerceViaIO *) node;
02090
02091 if (c->coerceformat == COERCE_IMPLICIT_CAST)
02092 return strip_implicit_coercions((Node *) c->arg);
02093 }
02094 else if (IsA(node, ArrayCoerceExpr))
02095 {
02096 ArrayCoerceExpr *c = (ArrayCoerceExpr *) node;
02097
02098 if (c->coerceformat == COERCE_IMPLICIT_CAST)
02099 return strip_implicit_coercions((Node *) c->arg);
02100 }
02101 else if (IsA(node, ConvertRowtypeExpr))
02102 {
02103 ConvertRowtypeExpr *c = (ConvertRowtypeExpr *) node;
02104
02105 if (c->convertformat == COERCE_IMPLICIT_CAST)
02106 return strip_implicit_coercions((Node *) c->arg);
02107 }
02108 else if (IsA(node, CoerceToDomain))
02109 {
02110 CoerceToDomain *c = (CoerceToDomain *) node;
02111
02112 if (c->coercionformat == COERCE_IMPLICIT_CAST)
02113 return strip_implicit_coercions((Node *) c->arg);
02114 }
02115 return node;
02116 }
02117
02118
02119
02120
02121
02122
02123
02124 static bool
02125 rowtype_field_matches(Oid rowtypeid, int fieldnum,
02126 Oid expectedtype, int32 expectedtypmod,
02127 Oid expectedcollation)
02128 {
02129 TupleDesc tupdesc;
02130 Form_pg_attribute attr;
02131
02132
02133 if (rowtypeid == RECORDOID)
02134 return true;
02135 tupdesc = lookup_rowtype_tupdesc(rowtypeid, -1);
02136 if (fieldnum <= 0 || fieldnum > tupdesc->natts)
02137 {
02138 ReleaseTupleDesc(tupdesc);
02139 return false;
02140 }
02141 attr = tupdesc->attrs[fieldnum - 1];
02142 if (attr->attisdropped ||
02143 attr->atttypid != expectedtype ||
02144 attr->atttypmod != expectedtypmod ||
02145 attr->attcollation != expectedcollation)
02146 {
02147 ReleaseTupleDesc(tupdesc);
02148 return false;
02149 }
02150 ReleaseTupleDesc(tupdesc);
02151 return true;
02152 }
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192 Node *
02193 eval_const_expressions(PlannerInfo *root, Node *node)
02194 {
02195 eval_const_expressions_context context;
02196
02197 if (root)
02198 context.boundParams = root->glob->boundParams;
02199 else
02200 context.boundParams = NULL;
02201 context.root = root;
02202 context.active_fns = NIL;
02203 context.case_val = NULL;
02204 context.estimate = false;
02205 return eval_const_expressions_mutator(node, &context);
02206 }
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225 Node *
02226 estimate_expression_value(PlannerInfo *root, Node *node)
02227 {
02228 eval_const_expressions_context context;
02229
02230 context.boundParams = root->glob->boundParams;
02231
02232 context.root = NULL;
02233 context.active_fns = NIL;
02234 context.case_val = NULL;
02235 context.estimate = true;
02236 return eval_const_expressions_mutator(node, &context);
02237 }
02238
02239 static Node *
02240 eval_const_expressions_mutator(Node *node,
02241 eval_const_expressions_context *context)
02242 {
02243 if (node == NULL)
02244 return NULL;
02245 switch (nodeTag(node))
02246 {
02247 case T_Param:
02248 {
02249 Param *param = (Param *) node;
02250
02251
02252 if (param->paramkind == PARAM_EXTERN &&
02253 context->boundParams != NULL &&
02254 param->paramid > 0 &&
02255 param->paramid <= context->boundParams->numParams)
02256 {
02257 ParamExternData *prm = &context->boundParams->params[param->paramid - 1];
02258
02259 if (OidIsValid(prm->ptype))
02260 {
02261
02262 if (context->estimate ||
02263 (prm->pflags & PARAM_FLAG_CONST))
02264 {
02265
02266
02267
02268
02269
02270
02271 int16 typLen;
02272 bool typByVal;
02273 Datum pval;
02274
02275 Assert(prm->ptype == param->paramtype);
02276 get_typlenbyval(param->paramtype,
02277 &typLen, &typByVal);
02278 if (prm->isnull || typByVal)
02279 pval = prm->value;
02280 else
02281 pval = datumCopy(prm->value, typByVal, typLen);
02282 return (Node *) makeConst(param->paramtype,
02283 param->paramtypmod,
02284 param->paramcollid,
02285 (int) typLen,
02286 pval,
02287 prm->isnull,
02288 typByVal);
02289 }
02290 }
02291 }
02292
02293
02294
02295
02296
02297 return (Node *) copyObject(param);
02298 }
02299 case T_FuncExpr:
02300 {
02301 FuncExpr *expr = (FuncExpr *) node;
02302 List *args = expr->args;
02303 Expr *simple;
02304 FuncExpr *newexpr;
02305
02306
02307
02308
02309
02310
02311
02312
02313 simple = simplify_function(expr->funcid,
02314 expr->funcresulttype,
02315 exprTypmod(node),
02316 expr->funccollid,
02317 expr->inputcollid,
02318 &args,
02319 expr->funcvariadic,
02320 true,
02321 true,
02322 context);
02323 if (simple)
02324 return (Node *) simple;
02325
02326
02327
02328
02329
02330
02331
02332 newexpr = makeNode(FuncExpr);
02333 newexpr->funcid = expr->funcid;
02334 newexpr->funcresulttype = expr->funcresulttype;
02335 newexpr->funcretset = expr->funcretset;
02336 newexpr->funcvariadic = expr->funcvariadic;
02337 newexpr->funcformat = expr->funcformat;
02338 newexpr->funccollid = expr->funccollid;
02339 newexpr->inputcollid = expr->inputcollid;
02340 newexpr->args = args;
02341 newexpr->location = expr->location;
02342 return (Node *) newexpr;
02343 }
02344 case T_OpExpr:
02345 {
02346 OpExpr *expr = (OpExpr *) node;
02347 List *args = expr->args;
02348 Expr *simple;
02349 OpExpr *newexpr;
02350
02351
02352
02353
02354
02355 set_opfuncid(expr);
02356
02357
02358
02359
02360
02361 simple = simplify_function(expr->opfuncid,
02362 expr->opresulttype, -1,
02363 expr->opcollid,
02364 expr->inputcollid,
02365 &args,
02366 false,
02367 true,
02368 true,
02369 context);
02370 if (simple)
02371 return (Node *) simple;
02372
02373
02374
02375
02376
02377
02378 if (expr->opno == BooleanEqualOperator ||
02379 expr->opno == BooleanNotEqualOperator)
02380 {
02381 simple = (Expr *) simplify_boolean_equality(expr->opno,
02382 args);
02383 if (simple)
02384 return (Node *) simple;
02385 }
02386
02387
02388
02389
02390
02391
02392 newexpr = makeNode(OpExpr);
02393 newexpr->opno = expr->opno;
02394 newexpr->opfuncid = expr->opfuncid;
02395 newexpr->opresulttype = expr->opresulttype;
02396 newexpr->opretset = expr->opretset;
02397 newexpr->opcollid = expr->opcollid;
02398 newexpr->inputcollid = expr->inputcollid;
02399 newexpr->args = args;
02400 newexpr->location = expr->location;
02401 return (Node *) newexpr;
02402 }
02403 case T_DistinctExpr:
02404 {
02405 DistinctExpr *expr = (DistinctExpr *) node;
02406 List *args;
02407 ListCell *arg;
02408 bool has_null_input = false;
02409 bool all_null_input = true;
02410 bool has_nonconst_input = false;
02411 Expr *simple;
02412 DistinctExpr *newexpr;
02413
02414
02415
02416
02417
02418
02419
02420 args = (List *) expression_tree_mutator((Node *) expr->args,
02421 eval_const_expressions_mutator,
02422 (void *) context);
02423
02424
02425
02426
02427
02428
02429 foreach(arg, args)
02430 {
02431 if (IsA(lfirst(arg), Const))
02432 {
02433 has_null_input |= ((Const *) lfirst(arg))->constisnull;
02434 all_null_input &= ((Const *) lfirst(arg))->constisnull;
02435 }
02436 else
02437 has_nonconst_input = true;
02438 }
02439
02440
02441 if (!has_nonconst_input)
02442 {
02443
02444 if (all_null_input)
02445 return makeBoolConst(false, false);
02446
02447
02448 if (has_null_input)
02449 return makeBoolConst(true, false);
02450
02451
02452
02453
02454
02455
02456
02457
02458 set_opfuncid((OpExpr *) expr);
02459
02460
02461
02462
02463
02464
02465 simple = simplify_function(expr->opfuncid,
02466 expr->opresulttype, -1,
02467 expr->opcollid,
02468 expr->inputcollid,
02469 &args,
02470 false,
02471 false,
02472 false,
02473 context);
02474 if (simple)
02475 {
02476
02477
02478
02479
02480 Const *csimple = (Const *) simple;
02481
02482 Assert(IsA(csimple, Const));
02483 csimple->constvalue =
02484 BoolGetDatum(!DatumGetBool(csimple->constvalue));
02485 return (Node *) csimple;
02486 }
02487 }
02488
02489
02490
02491
02492
02493
02494 newexpr = makeNode(DistinctExpr);
02495 newexpr->opno = expr->opno;
02496 newexpr->opfuncid = expr->opfuncid;
02497 newexpr->opresulttype = expr->opresulttype;
02498 newexpr->opretset = expr->opretset;
02499 newexpr->opcollid = expr->opcollid;
02500 newexpr->inputcollid = expr->inputcollid;
02501 newexpr->args = args;
02502 newexpr->location = expr->location;
02503 return (Node *) newexpr;
02504 }
02505 case T_BoolExpr:
02506 {
02507 BoolExpr *expr = (BoolExpr *) node;
02508
02509 switch (expr->boolop)
02510 {
02511 case OR_EXPR:
02512 {
02513 List *newargs;
02514 bool haveNull = false;
02515 bool forceTrue = false;
02516
02517 newargs = simplify_or_arguments(expr->args,
02518 context,
02519 &haveNull,
02520 &forceTrue);
02521 if (forceTrue)
02522 return makeBoolConst(true, false);
02523 if (haveNull)
02524 newargs = lappend(newargs,
02525 makeBoolConst(false, true));
02526
02527 if (newargs == NIL)
02528 return makeBoolConst(false, false);
02529
02530
02531
02532
02533
02534 if (list_length(newargs) == 1)
02535 return (Node *) linitial(newargs);
02536
02537 return (Node *) make_orclause(newargs);
02538 }
02539 case AND_EXPR:
02540 {
02541 List *newargs;
02542 bool haveNull = false;
02543 bool forceFalse = false;
02544
02545 newargs = simplify_and_arguments(expr->args,
02546 context,
02547 &haveNull,
02548 &forceFalse);
02549 if (forceFalse)
02550 return makeBoolConst(false, false);
02551 if (haveNull)
02552 newargs = lappend(newargs,
02553 makeBoolConst(false, true));
02554
02555 if (newargs == NIL)
02556 return makeBoolConst(true, false);
02557
02558
02559
02560
02561
02562 if (list_length(newargs) == 1)
02563 return (Node *) linitial(newargs);
02564
02565 return (Node *) make_andclause(newargs);
02566 }
02567 case NOT_EXPR:
02568 {
02569 Node *arg;
02570
02571 Assert(list_length(expr->args) == 1);
02572 arg = eval_const_expressions_mutator(linitial(expr->args),
02573 context);
02574
02575
02576
02577
02578
02579 return negate_clause(arg);
02580 }
02581 default:
02582 elog(ERROR, "unrecognized boolop: %d",
02583 (int) expr->boolop);
02584 break;
02585 }
02586 break;
02587 }
02588 case T_SubPlan:
02589 case T_AlternativeSubPlan:
02590
02591
02592
02593
02594
02595
02596
02597 return node;
02598 case T_RelabelType:
02599 {
02600
02601
02602
02603
02604
02605
02606 RelabelType *relabel = (RelabelType *) node;
02607 Node *arg;
02608
02609 arg = eval_const_expressions_mutator((Node *) relabel->arg,
02610 context);
02611
02612
02613
02614
02615
02616 while (arg && IsA(arg, RelabelType))
02617 arg = (Node *) ((RelabelType *) arg)->arg;
02618
02619 if (arg && IsA(arg, Const))
02620 {
02621 Const *con = (Const *) arg;
02622
02623 con->consttype = relabel->resulttype;
02624 con->consttypmod = relabel->resulttypmod;
02625 con->constcollid = relabel->resultcollid;
02626 return (Node *) con;
02627 }
02628 else
02629 {
02630 RelabelType *newrelabel = makeNode(RelabelType);
02631
02632 newrelabel->arg = (Expr *) arg;
02633 newrelabel->resulttype = relabel->resulttype;
02634 newrelabel->resulttypmod = relabel->resulttypmod;
02635 newrelabel->resultcollid = relabel->resultcollid;
02636 newrelabel->relabelformat = relabel->relabelformat;
02637 newrelabel->location = relabel->location;
02638 return (Node *) newrelabel;
02639 }
02640 }
02641 case T_CoerceViaIO:
02642 {
02643 CoerceViaIO *expr = (CoerceViaIO *) node;
02644 List *args;
02645 Oid outfunc;
02646 bool outtypisvarlena;
02647 Oid infunc;
02648 Oid intypioparam;
02649 Expr *simple;
02650 CoerceViaIO *newexpr;
02651
02652
02653 args = list_make1(expr->arg);
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664 getTypeOutputInfo(exprType((Node *) expr->arg),
02665 &outfunc, &outtypisvarlena);
02666 getTypeInputInfo(expr->resulttype,
02667 &infunc, &intypioparam);
02668
02669 simple = simplify_function(outfunc,
02670 CSTRINGOID, -1,
02671 InvalidOid,
02672 InvalidOid,
02673 &args,
02674 false,
02675 true,
02676 true,
02677 context);
02678 if (simple)
02679 {
02680
02681
02682
02683
02684
02685 args = list_make3(simple,
02686 makeConst(OIDOID,
02687 -1,
02688 InvalidOid,
02689 sizeof(Oid),
02690 ObjectIdGetDatum(intypioparam),
02691 false,
02692 true),
02693 makeConst(INT4OID,
02694 -1,
02695 InvalidOid,
02696 sizeof(int32),
02697 Int32GetDatum(-1),
02698 false,
02699 true));
02700
02701 simple = simplify_function(infunc,
02702 expr->resulttype, -1,
02703 expr->resultcollid,
02704 InvalidOid,
02705 &args,
02706 false,
02707 false,
02708 true,
02709 context);
02710 if (simple)
02711 return (Node *) simple;
02712 }
02713
02714
02715
02716
02717
02718
02719 newexpr = makeNode(CoerceViaIO);
02720 newexpr->arg = (Expr *) linitial(args);
02721 newexpr->resulttype = expr->resulttype;
02722 newexpr->resultcollid = expr->resultcollid;
02723 newexpr->coerceformat = expr->coerceformat;
02724 newexpr->location = expr->location;
02725 return (Node *) newexpr;
02726 }
02727 case T_ArrayCoerceExpr:
02728 {
02729 ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
02730 Expr *arg;
02731 ArrayCoerceExpr *newexpr;
02732
02733
02734
02735
02736
02737 arg = (Expr *) eval_const_expressions_mutator((Node *) expr->arg,
02738 context);
02739
02740 newexpr = makeNode(ArrayCoerceExpr);
02741 newexpr->arg = arg;
02742 newexpr->elemfuncid = expr->elemfuncid;
02743 newexpr->resulttype = expr->resulttype;
02744 newexpr->resulttypmod = expr->resulttypmod;
02745 newexpr->resultcollid = expr->resultcollid;
02746 newexpr->isExplicit = expr->isExplicit;
02747 newexpr->coerceformat = expr->coerceformat;
02748 newexpr->location = expr->location;
02749
02750
02751
02752
02753
02754 if (arg && IsA(arg, Const) &&
02755 (!OidIsValid(newexpr->elemfuncid) ||
02756 func_volatile(newexpr->elemfuncid) == PROVOLATILE_IMMUTABLE))
02757 return (Node *) evaluate_expr((Expr *) newexpr,
02758 newexpr->resulttype,
02759 newexpr->resulttypmod,
02760 newexpr->resultcollid);
02761
02762
02763 return (Node *) newexpr;
02764 }
02765 case T_CollateExpr:
02766 {
02767
02768
02769
02770
02771
02772
02773
02774
02775 CollateExpr *collate = (CollateExpr *) node;
02776 Node *arg;
02777
02778 arg = eval_const_expressions_mutator((Node *) collate->arg,
02779 context);
02780
02781 if (arg && IsA(arg, Const))
02782 {
02783 Const *con = (Const *) arg;
02784
02785 con->constcollid = collate->collOid;
02786 return (Node *) con;
02787 }
02788 else if (collate->collOid == exprCollation(arg))
02789 {
02790
02791 return arg;
02792 }
02793 else
02794 {
02795 RelabelType *relabel = makeNode(RelabelType);
02796
02797 relabel->resulttype = exprType(arg);
02798 relabel->resulttypmod = exprTypmod(arg);
02799 relabel->resultcollid = collate->collOid;
02800 relabel->relabelformat = COERCE_IMPLICIT_CAST;
02801 relabel->location = collate->location;
02802
02803
02804 while (arg && IsA(arg, RelabelType))
02805 arg = (Node *) ((RelabelType *) arg)->arg;
02806 relabel->arg = (Expr *) arg;
02807
02808 return (Node *) relabel;
02809 }
02810 }
02811 case T_CaseExpr:
02812 {
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843 CaseExpr *caseexpr = (CaseExpr *) node;
02844 CaseExpr *newcase;
02845 Node *save_case_val;
02846 Node *newarg;
02847 List *newargs;
02848 bool const_true_cond;
02849 Node *defresult = NULL;
02850 ListCell *arg;
02851
02852
02853 newarg = eval_const_expressions_mutator((Node *) caseexpr->arg,
02854 context);
02855
02856
02857 save_case_val = context->case_val;
02858 if (newarg && IsA(newarg, Const))
02859 {
02860 context->case_val = newarg;
02861 newarg = NULL;
02862 }
02863 else
02864 context->case_val = NULL;
02865
02866
02867 newargs = NIL;
02868 const_true_cond = false;
02869 foreach(arg, caseexpr->args)
02870 {
02871 CaseWhen *oldcasewhen = (CaseWhen *) lfirst(arg);
02872 Node *casecond;
02873 Node *caseresult;
02874
02875 Assert(IsA(oldcasewhen, CaseWhen));
02876
02877
02878 casecond = eval_const_expressions_mutator((Node *) oldcasewhen->expr,
02879 context);
02880
02881
02882
02883
02884
02885
02886 if (casecond && IsA(casecond, Const))
02887 {
02888 Const *const_input = (Const *) casecond;
02889
02890 if (const_input->constisnull ||
02891 !DatumGetBool(const_input->constvalue))
02892 continue;
02893
02894 const_true_cond = true;
02895 }
02896
02897
02898 caseresult = eval_const_expressions_mutator((Node *) oldcasewhen->result,
02899 context);
02900
02901
02902 if (!const_true_cond)
02903 {
02904 CaseWhen *newcasewhen = makeNode(CaseWhen);
02905
02906 newcasewhen->expr = (Expr *) casecond;
02907 newcasewhen->result = (Expr *) caseresult;
02908 newcasewhen->location = oldcasewhen->location;
02909 newargs = lappend(newargs, newcasewhen);
02910 continue;
02911 }
02912
02913
02914
02915
02916
02917
02918 defresult = caseresult;
02919 break;
02920 }
02921
02922
02923 if (!const_true_cond)
02924 defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
02925 context);
02926
02927 context->case_val = save_case_val;
02928
02929
02930
02931
02932
02933 if (newargs == NIL)
02934 return defresult;
02935
02936 newcase = makeNode(CaseExpr);
02937 newcase->casetype = caseexpr->casetype;
02938 newcase->casecollid = caseexpr->casecollid;
02939 newcase->arg = (Expr *) newarg;
02940 newcase->args = newargs;
02941 newcase->defresult = (Expr *) defresult;
02942 newcase->location = caseexpr->location;
02943 return (Node *) newcase;
02944 }
02945 case T_CaseTestExpr:
02946 {
02947
02948
02949
02950
02951
02952 if (context->case_val)
02953 return copyObject(context->case_val);
02954 else
02955 return copyObject(node);
02956 }
02957 case T_ArrayExpr:
02958 {
02959 ArrayExpr *arrayexpr = (ArrayExpr *) node;
02960 ArrayExpr *newarray;
02961 bool all_const = true;
02962 List *newelems;
02963 ListCell *element;
02964
02965 newelems = NIL;
02966 foreach(element, arrayexpr->elements)
02967 {
02968 Node *e;
02969
02970 e = eval_const_expressions_mutator((Node *) lfirst(element),
02971 context);
02972 if (!IsA(e, Const))
02973 all_const = false;
02974 newelems = lappend(newelems, e);
02975 }
02976
02977 newarray = makeNode(ArrayExpr);
02978 newarray->array_typeid = arrayexpr->array_typeid;
02979 newarray->array_collid = arrayexpr->array_collid;
02980 newarray->element_typeid = arrayexpr->element_typeid;
02981 newarray->elements = newelems;
02982 newarray->multidims = arrayexpr->multidims;
02983 newarray->location = arrayexpr->location;
02984
02985 if (all_const)
02986 return (Node *) evaluate_expr((Expr *) newarray,
02987 newarray->array_typeid,
02988 exprTypmod(node),
02989 newarray->array_collid);
02990
02991 return (Node *) newarray;
02992 }
02993 case T_CoalesceExpr:
02994 {
02995 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
02996 CoalesceExpr *newcoalesce;
02997 List *newargs;
02998 ListCell *arg;
02999
03000 newargs = NIL;
03001 foreach(arg, coalesceexpr->args)
03002 {
03003 Node *e;
03004
03005 e = eval_const_expressions_mutator((Node *) lfirst(arg),
03006 context);
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016 if (IsA(e, Const))
03017 {
03018 if (((Const *) e)->constisnull)
03019 continue;
03020 if (newargs == NIL)
03021 return e;
03022 newargs = lappend(newargs, e);
03023 break;
03024 }
03025 newargs = lappend(newargs, e);
03026 }
03027
03028
03029
03030
03031
03032 if (newargs == NIL)
03033 return (Node *) makeNullConst(coalesceexpr->coalescetype,
03034 -1,
03035 coalesceexpr->coalescecollid);
03036
03037 newcoalesce = makeNode(CoalesceExpr);
03038 newcoalesce->coalescetype = coalesceexpr->coalescetype;
03039 newcoalesce->coalescecollid = coalesceexpr->coalescecollid;
03040 newcoalesce->args = newargs;
03041 newcoalesce->location = coalesceexpr->location;
03042 return (Node *) newcoalesce;
03043 }
03044 case T_FieldSelect:
03045 {
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058 FieldSelect *fselect = (FieldSelect *) node;
03059 FieldSelect *newfselect;
03060 Node *arg;
03061
03062 arg = eval_const_expressions_mutator((Node *) fselect->arg,
03063 context);
03064 if (arg && IsA(arg, Var) &&
03065 ((Var *) arg)->varattno == InvalidAttrNumber)
03066 {
03067 if (rowtype_field_matches(((Var *) arg)->vartype,
03068 fselect->fieldnum,
03069 fselect->resulttype,
03070 fselect->resulttypmod,
03071 fselect->resultcollid))
03072 return (Node *) makeVar(((Var *) arg)->varno,
03073 fselect->fieldnum,
03074 fselect->resulttype,
03075 fselect->resulttypmod,
03076 fselect->resultcollid,
03077 ((Var *) arg)->varlevelsup);
03078 }
03079 if (arg && IsA(arg, RowExpr))
03080 {
03081 RowExpr *rowexpr = (RowExpr *) arg;
03082
03083 if (fselect->fieldnum > 0 &&
03084 fselect->fieldnum <= list_length(rowexpr->args))
03085 {
03086 Node *fld = (Node *) list_nth(rowexpr->args,
03087 fselect->fieldnum - 1);
03088
03089 if (rowtype_field_matches(rowexpr->row_typeid,
03090 fselect->fieldnum,
03091 fselect->resulttype,
03092 fselect->resulttypmod,
03093 fselect->resultcollid) &&
03094 fselect->resulttype == exprType(fld) &&
03095 fselect->resulttypmod == exprTypmod(fld) &&
03096 fselect->resultcollid == exprCollation(fld))
03097 return fld;
03098 }
03099 }
03100 newfselect = makeNode(FieldSelect);
03101 newfselect->arg = (Expr *) arg;
03102 newfselect->fieldnum = fselect->fieldnum;
03103 newfselect->resulttype = fselect->resulttype;
03104 newfselect->resulttypmod = fselect->resulttypmod;
03105 newfselect->resultcollid = fselect->resultcollid;
03106 return (Node *) newfselect;
03107 }
03108 case T_NullTest:
03109 {
03110 NullTest *ntest = (NullTest *) node;
03111 NullTest *newntest;
03112 Node *arg;
03113
03114 arg = eval_const_expressions_mutator((Node *) ntest->arg,
03115 context);
03116 if (arg && IsA(arg, RowExpr))
03117 {
03118
03119
03120
03121
03122
03123
03124 RowExpr *rarg = (RowExpr *) arg;
03125 List *newargs = NIL;
03126 ListCell *l;
03127
03128 Assert(ntest->argisrow);
03129
03130 foreach(l, rarg->args)
03131 {
03132 Node *relem = (Node *) lfirst(l);
03133
03134
03135
03136
03137
03138 if (relem && IsA(relem, Const))
03139 {
03140 Const *carg = (Const *) relem;
03141
03142 if (carg->constisnull ?
03143 (ntest->nulltesttype == IS_NOT_NULL) :
03144 (ntest->nulltesttype == IS_NULL))
03145 return makeBoolConst(false, false);
03146 continue;
03147 }
03148 newntest = makeNode(NullTest);
03149 newntest->arg = (Expr *) relem;
03150 newntest->nulltesttype = ntest->nulltesttype;
03151 newntest->argisrow = type_is_rowtype(exprType(relem));
03152 newargs = lappend(newargs, newntest);
03153 }
03154
03155 if (newargs == NIL)
03156 return makeBoolConst(true, false);
03157
03158 if (list_length(newargs) == 1)
03159 return (Node *) linitial(newargs);
03160
03161 return (Node *) make_andclause(newargs);
03162 }
03163 if (!ntest->argisrow && arg && IsA(arg, Const))
03164 {
03165 Const *carg = (Const *) arg;
03166 bool result;
03167
03168 switch (ntest->nulltesttype)
03169 {
03170 case IS_NULL:
03171 result = carg->constisnull;
03172 break;
03173 case IS_NOT_NULL:
03174 result = !carg->constisnull;
03175 break;
03176 default:
03177 elog(ERROR, "unrecognized nulltesttype: %d",
03178 (int) ntest->nulltesttype);
03179 result = false;
03180 break;
03181 }
03182
03183 return makeBoolConst(result, false);
03184 }
03185
03186 newntest = makeNode(NullTest);
03187 newntest->arg = (Expr *) arg;
03188 newntest->nulltesttype = ntest->nulltesttype;
03189 newntest->argisrow = ntest->argisrow;
03190 return (Node *) newntest;
03191 }
03192 case T_BooleanTest:
03193 {
03194 BooleanTest *btest = (BooleanTest *) node;
03195 BooleanTest *newbtest;
03196 Node *arg;
03197
03198 arg = eval_const_expressions_mutator((Node *) btest->arg,
03199 context);
03200 if (arg && IsA(arg, Const))
03201 {
03202 Const *carg = (Const *) arg;
03203 bool result;
03204
03205 switch (btest->booltesttype)
03206 {
03207 case IS_TRUE:
03208 result = (!carg->constisnull &&
03209 DatumGetBool(carg->constvalue));
03210 break;
03211 case IS_NOT_TRUE:
03212 result = (carg->constisnull ||
03213 !DatumGetBool(carg->constvalue));
03214 break;
03215 case IS_FALSE:
03216 result = (!carg->constisnull &&
03217 !DatumGetBool(carg->constvalue));
03218 break;
03219 case IS_NOT_FALSE:
03220 result = (carg->constisnull ||
03221 DatumGetBool(carg->constvalue));
03222 break;
03223 case IS_UNKNOWN:
03224 result = carg->constisnull;
03225 break;
03226 case IS_NOT_UNKNOWN:
03227 result = !carg->constisnull;
03228 break;
03229 default:
03230 elog(ERROR, "unrecognized booltesttype: %d",
03231 (int) btest->booltesttype);
03232 result = false;
03233 break;
03234 }
03235
03236 return makeBoolConst(result, false);
03237 }
03238
03239 newbtest = makeNode(BooleanTest);
03240 newbtest->arg = (Expr *) arg;
03241 newbtest->booltesttype = btest->booltesttype;
03242 return (Node *) newbtest;
03243 }
03244 case T_PlaceHolderVar:
03245
03246
03247
03248
03249
03250
03251
03252
03253 if (context->estimate)
03254 {
03255 PlaceHolderVar *phv = (PlaceHolderVar *) node;
03256
03257 return eval_const_expressions_mutator((Node *) phv->phexpr,
03258 context);
03259 }
03260 break;
03261 default:
03262 break;
03263 }
03264
03265
03266
03267
03268
03269
03270
03271
03272 return expression_tree_mutator(node, eval_const_expressions_mutator,
03273 (void *) context);
03274 }
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295 static List *
03296 simplify_or_arguments(List *args,
03297 eval_const_expressions_context *context,
03298 bool *haveNull, bool *forceTrue)
03299 {
03300 List *newargs = NIL;
03301 List *unprocessed_args;
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311 unprocessed_args = list_copy(args);
03312 while (unprocessed_args)
03313 {
03314 Node *arg = (Node *) linitial(unprocessed_args);
03315
03316 unprocessed_args = list_delete_first(unprocessed_args);
03317
03318
03319 if (or_clause(arg))
03320 {
03321 List *subargs = list_copy(((BoolExpr *) arg)->args);
03322
03323
03324 if (!unprocessed_args)
03325 unprocessed_args = subargs;
03326 else
03327 {
03328 List *oldhdr = unprocessed_args;
03329
03330 unprocessed_args = list_concat(subargs, unprocessed_args);
03331 pfree(oldhdr);
03332 }
03333 continue;
03334 }
03335
03336
03337 arg = eval_const_expressions_mutator(arg, context);
03338
03339
03340
03341
03342
03343
03344
03345 if (or_clause(arg))
03346 {
03347 List *subargs = list_copy(((BoolExpr *) arg)->args);
03348
03349 unprocessed_args = list_concat(subargs, unprocessed_args);
03350 continue;
03351 }
03352
03353
03354
03355
03356
03357 if (IsA(arg, Const))
03358 {
03359 Const *const_input = (Const *) arg;
03360
03361 if (const_input->constisnull)
03362 *haveNull = true;
03363 else if (DatumGetBool(const_input->constvalue))
03364 {
03365 *forceTrue = true;
03366
03367
03368
03369
03370
03371
03372 return NIL;
03373 }
03374
03375 continue;
03376 }
03377
03378
03379 newargs = lappend(newargs, arg);
03380 }
03381
03382 return newargs;
03383 }
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404 static List *
03405 simplify_and_arguments(List *args,
03406 eval_const_expressions_context *context,
03407 bool *haveNull, bool *forceFalse)
03408 {
03409 List *newargs = NIL;
03410 List *unprocessed_args;
03411
03412
03413 unprocessed_args = list_copy(args);
03414 while (unprocessed_args)
03415 {
03416 Node *arg = (Node *) linitial(unprocessed_args);
03417
03418 unprocessed_args = list_delete_first(unprocessed_args);
03419
03420
03421 if (and_clause(arg))
03422 {
03423 List *subargs = list_copy(((BoolExpr *) arg)->args);
03424
03425
03426 if (!unprocessed_args)
03427 unprocessed_args = subargs;
03428 else
03429 {
03430 List *oldhdr = unprocessed_args;
03431
03432 unprocessed_args = list_concat(subargs, unprocessed_args);
03433 pfree(oldhdr);
03434 }
03435 continue;
03436 }
03437
03438
03439 arg = eval_const_expressions_mutator(arg, context);
03440
03441
03442
03443
03444
03445
03446
03447 if (and_clause(arg))
03448 {
03449 List *subargs = list_copy(((BoolExpr *) arg)->args);
03450
03451 unprocessed_args = list_concat(subargs, unprocessed_args);
03452 continue;
03453 }
03454
03455
03456
03457
03458
03459 if (IsA(arg, Const))
03460 {
03461 Const *const_input = (Const *) arg;
03462
03463 if (const_input->constisnull)
03464 *haveNull = true;
03465 else if (!DatumGetBool(const_input->constvalue))
03466 {
03467 *forceFalse = true;
03468
03469
03470
03471
03472
03473
03474 return NIL;
03475 }
03476
03477 continue;
03478 }
03479
03480
03481 newargs = lappend(newargs, arg);
03482 }
03483
03484 return newargs;
03485 }
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504 static Node *
03505 simplify_boolean_equality(Oid opno, List *args)
03506 {
03507 Node *leftop;
03508 Node *rightop;
03509
03510 Assert(list_length(args) == 2);
03511 leftop = linitial(args);
03512 rightop = lsecond(args);
03513 if (leftop && IsA(leftop, Const))
03514 {
03515 Assert(!((Const *) leftop)->constisnull);
03516 if (opno == BooleanEqualOperator)
03517 {
03518 if (DatumGetBool(((Const *) leftop)->constvalue))
03519 return rightop;
03520 else
03521 return negate_clause(rightop);
03522 }
03523 else
03524 {
03525 if (DatumGetBool(((Const *) leftop)->constvalue))
03526 return negate_clause(rightop);
03527 else
03528 return rightop;
03529 }
03530 }
03531 if (rightop && IsA(rightop, Const))
03532 {
03533 Assert(!((Const *) rightop)->constisnull);
03534 if (opno == BooleanEqualOperator)
03535 {
03536 if (DatumGetBool(((Const *) rightop)->constvalue))
03537 return leftop;
03538 else
03539 return negate_clause(leftop);
03540 }
03541 else
03542 {
03543 if (DatumGetBool(((Const *) rightop)->constvalue))
03544 return negate_clause(leftop);
03545 else
03546 return leftop;
03547 }
03548 }
03549 return NULL;
03550 }
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573 static Expr *
03574 simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
03575 Oid result_collid, Oid input_collid, List **args_p,
03576 bool funcvariadic, bool process_args, bool allow_non_const,
03577 eval_const_expressions_context *context)
03578 {
03579 List *args = *args_p;
03580 HeapTuple func_tuple;
03581 Form_pg_proc func_form;
03582 Expr *newexpr;
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596 func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
03597 if (!HeapTupleIsValid(func_tuple))
03598 elog(ERROR, "cache lookup failed for function %u", funcid);
03599 func_form = (Form_pg_proc) GETSTRUCT(func_tuple);
03600
03601
03602
03603
03604
03605
03606
03607 if (process_args)
03608 {
03609 args = expand_function_arguments(args, result_type, func_tuple);
03610 args = (List *) expression_tree_mutator((Node *) args,
03611 eval_const_expressions_mutator,
03612 (void *) context);
03613
03614 *args_p = args;
03615 }
03616
03617
03618
03619 newexpr = evaluate_function(funcid, result_type, result_typmod,
03620 result_collid, input_collid,
03621 args, funcvariadic,
03622 func_tuple, context);
03623
03624 if (!newexpr && allow_non_const && OidIsValid(func_form->protransform))
03625 {
03626
03627
03628
03629
03630
03631 FuncExpr fexpr;
03632
03633 fexpr.xpr.type = T_FuncExpr;
03634 fexpr.funcid = funcid;
03635 fexpr.funcresulttype = result_type;
03636 fexpr.funcretset = func_form->proretset;
03637 fexpr.funcvariadic = funcvariadic;
03638 fexpr.funcformat = COERCE_EXPLICIT_CALL;
03639 fexpr.funccollid = result_collid;
03640 fexpr.inputcollid = input_collid;
03641 fexpr.args = args;
03642 fexpr.location = -1;
03643
03644 newexpr = (Expr *)
03645 DatumGetPointer(OidFunctionCall1(func_form->protransform,
03646 PointerGetDatum(&fexpr)));
03647 }
03648
03649 if (!newexpr && allow_non_const)
03650 newexpr = inline_function(funcid, result_type, result_collid,
03651 input_collid, args, funcvariadic,
03652 func_tuple, context);
03653
03654 ReleaseSysCache(func_tuple);
03655
03656 return newexpr;
03657 }
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670 static List *
03671 expand_function_arguments(List *args, Oid result_type, HeapTuple func_tuple)
03672 {
03673 Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
03674 bool has_named_args = false;
03675 ListCell *lc;
03676
03677
03678 foreach(lc, args)
03679 {
03680 Node *arg = (Node *) lfirst(lc);
03681
03682 if (IsA(arg, NamedArgExpr))
03683 {
03684 has_named_args = true;
03685 break;
03686 }
03687 }
03688
03689
03690 if (has_named_args)
03691 {
03692 args = reorder_function_arguments(args, func_tuple);
03693
03694 recheck_cast_function_args(args, result_type, func_tuple);
03695 }
03696 else if (list_length(args) < funcform->pronargs)
03697 {
03698
03699 args = add_function_defaults(args, func_tuple);
03700
03701 recheck_cast_function_args(args, result_type, func_tuple);
03702 }
03703
03704 return args;
03705 }
03706
03707
03708
03709
03710
03711
03712
03713 static List *
03714 reorder_function_arguments(List *args, HeapTuple func_tuple)
03715 {
03716 Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
03717 int pronargs = funcform->pronargs;
03718 int nargsprovided = list_length(args);
03719 Node *argarray[FUNC_MAX_ARGS];
03720 ListCell *lc;
03721 int i;
03722
03723 Assert(nargsprovided <= pronargs);
03724 if (pronargs > FUNC_MAX_ARGS)
03725 elog(ERROR, "too many function arguments");
03726 MemSet(argarray, 0, pronargs * sizeof(Node *));
03727
03728
03729 i = 0;
03730 foreach(lc, args)
03731 {
03732 Node *arg = (Node *) lfirst(lc);
03733
03734 if (!IsA(arg, NamedArgExpr))
03735 {
03736
03737 Assert(argarray[i] == NULL);
03738 argarray[i++] = arg;
03739 }
03740 else
03741 {
03742 NamedArgExpr *na = (NamedArgExpr *) arg;
03743
03744 Assert(argarray[na->argnumber] == NULL);
03745 argarray[na->argnumber] = (Node *) na->arg;
03746 }
03747 }
03748
03749
03750
03751
03752
03753 if (nargsprovided < pronargs)
03754 {
03755 List *defaults = fetch_function_defaults(func_tuple);
03756
03757 i = pronargs - funcform->pronargdefaults;
03758 foreach(lc, defaults)
03759 {
03760 if (argarray[i] == NULL)
03761 argarray[i] = (Node *) lfirst(lc);
03762 i++;
03763 }
03764 }
03765
03766
03767 args = NIL;
03768 for (i = 0; i < pronargs; i++)
03769 {
03770 Assert(argarray[i] != NULL);
03771 args = lappend(args, argarray[i]);
03772 }
03773
03774 return args;
03775 }
03776
03777
03778
03779
03780
03781
03782
03783 static List *
03784 add_function_defaults(List *args, HeapTuple func_tuple)
03785 {
03786 Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
03787 int nargsprovided = list_length(args);
03788 List *defaults;
03789 int ndelete;
03790
03791
03792 defaults = fetch_function_defaults(func_tuple);
03793
03794
03795 ndelete = nargsprovided + list_length(defaults) - funcform->pronargs;
03796 if (ndelete < 0)
03797 elog(ERROR, "not enough default arguments");
03798 while (ndelete-- > 0)
03799 defaults = list_delete_first(defaults);
03800
03801
03802 return list_concat(list_copy(args), defaults);
03803 }
03804
03805
03806
03807
03808 static List *
03809 fetch_function_defaults(HeapTuple func_tuple)
03810 {
03811 List *defaults;
03812 Datum proargdefaults;
03813 bool isnull;
03814 char *str;
03815
03816
03817 proargdefaults = SysCacheGetAttr(PROCOID, func_tuple,
03818 Anum_pg_proc_proargdefaults,
03819 &isnull);
03820 if (isnull)
03821 elog(ERROR, "not enough default arguments");
03822 str = TextDatumGetCString(proargdefaults);
03823 defaults = (List *) stringToNode(str);
03824 Assert(IsA(defaults, List));
03825 pfree(str);
03826 return defaults;
03827 }
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844 static void
03845 recheck_cast_function_args(List *args, Oid result_type, HeapTuple func_tuple)
03846 {
03847 Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
03848 int nargs;
03849 Oid actual_arg_types[FUNC_MAX_ARGS];
03850 Oid declared_arg_types[FUNC_MAX_ARGS];
03851 Oid rettype;
03852 ListCell *lc;
03853
03854 if (list_length(args) > FUNC_MAX_ARGS)
03855 elog(ERROR, "too many function arguments");
03856 nargs = 0;
03857 foreach(lc, args)
03858 {
03859 actual_arg_types[nargs++] = exprType((Node *) lfirst(lc));
03860 }
03861 Assert(nargs == funcform->pronargs);
03862 memcpy(declared_arg_types, funcform->proargtypes.values,
03863 funcform->pronargs * sizeof(Oid));
03864 rettype = enforce_generic_type_consistency(actual_arg_types,
03865 declared_arg_types,
03866 nargs,
03867 funcform->prorettype,
03868 false);
03869
03870 if (rettype != result_type)
03871 elog(ERROR, "function's resolved result type changed during planning");
03872
03873
03874 make_fn_arguments(NULL, args, actual_arg_types, declared_arg_types);
03875 }
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888 static Expr *
03889 evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
03890 Oid result_collid, Oid input_collid, List *args,
03891 bool funcvariadic,
03892 HeapTuple func_tuple,
03893 eval_const_expressions_context *context)
03894 {
03895 Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
03896 bool has_nonconst_input = false;
03897 bool has_null_input = false;
03898 ListCell *arg;
03899 FuncExpr *newexpr;
03900
03901
03902
03903
03904 if (funcform->proretset)
03905 return NULL;
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918 if (funcform->prorettype == RECORDOID)
03919 return NULL;
03920
03921
03922
03923
03924 foreach(arg, args)
03925 {
03926 if (IsA(lfirst(arg), Const))
03927 has_null_input |= ((Const *) lfirst(arg))->constisnull;
03928 else
03929 has_nonconst_input = true;
03930 }
03931
03932
03933
03934
03935
03936
03937
03938 if (funcform->proisstrict && has_null_input)
03939 return (Expr *) makeNullConst(result_type, result_typmod,
03940 result_collid);
03941
03942
03943
03944
03945
03946
03947 if (has_nonconst_input)
03948 return NULL;
03949
03950
03951
03952
03953
03954
03955
03956
03957 if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
03958 ;
03959 else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
03960 ;
03961 else
03962 return NULL;
03963
03964
03965
03966
03967
03968
03969 newexpr = makeNode(FuncExpr);
03970 newexpr->funcid = funcid;
03971 newexpr->funcresulttype = result_type;
03972 newexpr->funcretset = false;
03973 newexpr->funcvariadic = funcvariadic;
03974 newexpr->funcformat = COERCE_EXPLICIT_CALL;
03975 newexpr->funccollid = result_collid;
03976 newexpr->inputcollid = input_collid;
03977 newexpr->args = args;
03978 newexpr->location = -1;
03979
03980 return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
03981 result_collid);
03982 }
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013 static Expr *
04014 inline_function(Oid funcid, Oid result_type, Oid result_collid,
04015 Oid input_collid, List *args,
04016 bool funcvariadic,
04017 HeapTuple func_tuple,
04018 eval_const_expressions_context *context)
04019 {
04020 Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
04021 char *src;
04022 Datum tmp;
04023 bool isNull;
04024 bool modifyTargetList;
04025 MemoryContext oldcxt;
04026 MemoryContext mycxt;
04027 inline_error_callback_arg callback_arg;
04028 ErrorContextCallback sqlerrcontext;
04029 FuncExpr *fexpr;
04030 SQLFunctionParseInfoPtr pinfo;
04031 ParseState *pstate;
04032 List *raw_parsetree_list;
04033 Query *querytree;
04034 Node *newexpr;
04035 int *usecounts;
04036 ListCell *arg;
04037 int i;
04038
04039
04040
04041
04042
04043 if (funcform->prolang != SQLlanguageId ||
04044 funcform->prosecdef ||
04045 funcform->proretset ||
04046 funcform->prorettype == RECORDOID ||
04047 !heap_attisnull(func_tuple, Anum_pg_proc_proconfig) ||
04048 funcform->pronargs != list_length(args))
04049 return NULL;
04050
04051
04052 if (list_member_oid(context->active_fns, funcid))
04053 return NULL;
04054
04055
04056 if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
04057 return NULL;
04058
04059
04060 if (FmgrHookIsNeeded(funcid))
04061 return NULL;
04062
04063
04064
04065
04066
04067 mycxt = AllocSetContextCreate(CurrentMemoryContext,
04068 "inline_function",
04069 ALLOCSET_DEFAULT_MINSIZE,
04070 ALLOCSET_DEFAULT_INITSIZE,
04071 ALLOCSET_DEFAULT_MAXSIZE);
04072 oldcxt = MemoryContextSwitchTo(mycxt);
04073
04074
04075 tmp = SysCacheGetAttr(PROCOID,
04076 func_tuple,
04077 Anum_pg_proc_prosrc,
04078 &isNull);
04079 if (isNull)
04080 elog(ERROR, "null prosrc for function %u", funcid);
04081 src = TextDatumGetCString(tmp);
04082
04083
04084
04085
04086
04087 callback_arg.proname = NameStr(funcform->proname);
04088 callback_arg.prosrc = src;
04089
04090 sqlerrcontext.callback = sql_inline_error_callback;
04091 sqlerrcontext.arg = (void *) &callback_arg;
04092 sqlerrcontext.previous = error_context_stack;
04093 error_context_stack = &sqlerrcontext;
04094
04095
04096
04097
04098
04099
04100
04101 fexpr = makeNode(FuncExpr);
04102 fexpr->funcid = funcid;
04103 fexpr->funcresulttype = result_type;
04104 fexpr->funcretset = false;
04105 fexpr->funcvariadic = funcvariadic;
04106 fexpr->funcformat = COERCE_EXPLICIT_CALL;
04107 fexpr->funccollid = result_collid;
04108 fexpr->inputcollid = input_collid;
04109 fexpr->args = args;
04110 fexpr->location = -1;
04111
04112 pinfo = prepare_sql_fn_parse_info(func_tuple,
04113 (Node *) fexpr,
04114 input_collid);
04115
04116
04117
04118
04119
04120
04121
04122 raw_parsetree_list = pg_parse_query(src);
04123 if (list_length(raw_parsetree_list) != 1)
04124 goto fail;
04125
04126 pstate = make_parsestate(NULL);
04127 pstate->p_sourcetext = src;
04128 sql_fn_parser_setup(pstate, pinfo);
04129
04130 querytree = transformTopLevelStmt(pstate, linitial(raw_parsetree_list));
04131
04132 free_parsestate(pstate);
04133
04134
04135
04136
04137 if (!IsA(querytree, Query) ||
04138 querytree->commandType != CMD_SELECT ||
04139 querytree->utilityStmt ||
04140 querytree->hasAggs ||
04141 querytree->hasWindowFuncs ||
04142 querytree->hasSubLinks ||
04143 querytree->cteList ||
04144 querytree->rtable ||
04145 querytree->jointree->fromlist ||
04146 querytree->jointree->quals ||
04147 querytree->groupClause ||
04148 querytree->havingQual ||
04149 querytree->windowClause ||
04150 querytree->distinctClause ||
04151 querytree->sortClause ||
04152 querytree->limitOffset ||
04153 querytree->limitCount ||
04154 querytree->setOperations ||
04155 list_length(querytree->targetList) != 1)
04156 goto fail;
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168 if (check_sql_fn_retval(funcid, result_type, list_make1(querytree),
04169 &modifyTargetList, NULL))
04170 goto fail;
04171
04172
04173 newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
04174
04175
04176 Assert(exprType(newexpr) == result_type);
04177
04178 Assert(!modifyTargetList);
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189 if (expression_returns_set(newexpr))
04190 goto fail;
04191
04192 if (funcform->provolatile == PROVOLATILE_IMMUTABLE &&
04193 contain_mutable_functions(newexpr))
04194 goto fail;
04195 else if (funcform->provolatile == PROVOLATILE_STABLE &&
04196 contain_volatile_functions(newexpr))
04197 goto fail;
04198
04199 if (funcform->proisstrict &&
04200 contain_nonstrict_functions(newexpr))
04201 goto fail;
04202
04203
04204
04205
04206
04207
04208
04209 usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
04210 newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
04211 args, usecounts);
04212
04213
04214 i = 0;
04215 foreach(arg, args)
04216 {
04217 Node *param = lfirst(arg);
04218
04219 if (usecounts[i] == 0)
04220 {
04221
04222 if (funcform->proisstrict)
04223 goto fail;
04224 }
04225 else if (usecounts[i] != 1)
04226 {
04227
04228 QualCost eval_cost;
04229
04230
04231
04232
04233
04234
04235
04236 if (contain_subplans(param))
04237 goto fail;
04238 cost_qual_eval(&eval_cost, list_make1(param), NULL);
04239 if (eval_cost.startup + eval_cost.per_tuple >
04240 10 * cpu_operator_cost)
04241 goto fail;
04242
04243
04244
04245
04246
04247 if (contain_volatile_functions(param))
04248 goto fail;
04249 }
04250 i++;
04251 }
04252
04253
04254
04255
04256
04257 MemoryContextSwitchTo(oldcxt);
04258
04259 newexpr = copyObject(newexpr);
04260
04261 MemoryContextDelete(mycxt);
04262
04263
04264
04265
04266
04267
04268
04269 if (OidIsValid(result_collid))
04270 {
04271 Oid exprcoll = exprCollation(newexpr);
04272
04273 if (OidIsValid(exprcoll) && exprcoll != result_collid)
04274 {
04275 CollateExpr *newnode = makeNode(CollateExpr);
04276
04277 newnode->arg = (Expr *) newexpr;
04278 newnode->collOid = result_collid;
04279 newnode->location = -1;
04280
04281 newexpr = (Node *) newnode;
04282 }
04283 }
04284
04285
04286
04287
04288
04289 if (context->root)
04290 record_plan_function_dependency(context->root, funcid);
04291
04292
04293
04294
04295
04296 context->active_fns = lcons_oid(funcid, context->active_fns);
04297 newexpr = eval_const_expressions_mutator(newexpr, context);
04298 context->active_fns = list_delete_first(context->active_fns);
04299
04300 error_context_stack = sqlerrcontext.previous;
04301
04302 return (Expr *) newexpr;
04303
04304
04305 fail:
04306 MemoryContextSwitchTo(oldcxt);
04307 MemoryContextDelete(mycxt);
04308 error_context_stack = sqlerrcontext.previous;
04309
04310 return NULL;
04311 }
04312
04313
04314
04315
04316 static Node *
04317 substitute_actual_parameters(Node *expr, int nargs, List *args,
04318 int *usecounts)
04319 {
04320 substitute_actual_parameters_context context;
04321
04322 context.nargs = nargs;
04323 context.args = args;
04324 context.usecounts = usecounts;
04325
04326 return substitute_actual_parameters_mutator(expr, &context);
04327 }
04328
04329 static Node *
04330 substitute_actual_parameters_mutator(Node *node,
04331 substitute_actual_parameters_context *context)
04332 {
04333 if (node == NULL)
04334 return NULL;
04335 if (IsA(node, Param))
04336 {
04337 Param *param = (Param *) node;
04338
04339 if (param->paramkind != PARAM_EXTERN)
04340 elog(ERROR, "unexpected paramkind: %d", (int) param->paramkind);
04341 if (param->paramid <= 0 || param->paramid > context->nargs)
04342 elog(ERROR, "invalid paramid: %d", param->paramid);
04343
04344
04345 context->usecounts[param->paramid - 1]++;
04346
04347
04348
04349 return list_nth(context->args, param->paramid - 1);
04350 }
04351 return expression_tree_mutator(node, substitute_actual_parameters_mutator,
04352 (void *) context);
04353 }
04354
04355
04356
04357
04358 static void
04359 sql_inline_error_callback(void *arg)
04360 {
04361 inline_error_callback_arg *callback_arg = (inline_error_callback_arg *) arg;
04362 int syntaxerrposition;
04363
04364
04365 syntaxerrposition = geterrposition();
04366 if (syntaxerrposition > 0)
04367 {
04368 errposition(0);
04369 internalerrposition(syntaxerrposition);
04370 internalerrquery(callback_arg->prosrc);
04371 }
04372
04373 errcontext("SQL function \"%s\" during inlining", callback_arg->proname);
04374 }
04375
04376
04377
04378
04379
04380
04381
04382 static Expr *
04383 evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
04384 Oid result_collation)
04385 {
04386 EState *estate;
04387 ExprState *exprstate;
04388 MemoryContext oldcontext;
04389 Datum const_val;
04390 bool const_is_null;
04391 int16 resultTypLen;
04392 bool resultTypByVal;
04393
04394
04395
04396
04397 estate = CreateExecutorState();
04398
04399
04400 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
04401
04402
04403 fix_opfuncids((Node *) expr);
04404
04405
04406
04407
04408
04409 exprstate = ExecInitExpr(expr, NULL);
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419 const_val = ExecEvalExprSwitchContext(exprstate,
04420 GetPerTupleExprContext(estate),
04421 &const_is_null, NULL);
04422
04423
04424 get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
04425
04426
04427 MemoryContextSwitchTo(oldcontext);
04428
04429
04430
04431
04432
04433
04434
04435
04436 if (!const_is_null)
04437 {
04438 if (resultTypLen == -1)
04439 const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
04440 else
04441 const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
04442 }
04443
04444
04445 FreeExecutorState(estate);
04446
04447
04448
04449
04450 return (Expr *) makeConst(result_type, result_typmod, result_collation,
04451 resultTypLen,
04452 const_val, const_is_null,
04453 resultTypByVal);
04454 }
04455
04456
04457
04458
04459
04460
04461
04462
04463
04464
04465
04466
04467
04468
04469 Query *
04470 inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
04471 {
04472 FuncExpr *fexpr;
04473 Oid func_oid;
04474 HeapTuple func_tuple;
04475 Form_pg_proc funcform;
04476 char *src;
04477 Datum tmp;
04478 bool isNull;
04479 bool modifyTargetList;
04480 MemoryContext oldcxt;
04481 MemoryContext mycxt;
04482 List *saveInvalItems;
04483 inline_error_callback_arg callback_arg;
04484 ErrorContextCallback sqlerrcontext;
04485 SQLFunctionParseInfoPtr pinfo;
04486 List *raw_parsetree_list;
04487 List *querytree_list;
04488 Query *querytree;
04489
04490 Assert(rte->rtekind == RTE_FUNCTION);
04491
04492
04493
04494
04495
04496
04497
04498 check_stack_depth();
04499
04500
04501 fexpr = (FuncExpr *) rte->funcexpr;
04502 if (fexpr == NULL || !IsA(fexpr, FuncExpr))
04503 return NULL;
04504 func_oid = fexpr->funcid;
04505
04506
04507
04508
04509
04510
04511 if (!fexpr->funcretset)
04512 return NULL;
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522
04523 if (contain_volatile_functions((Node *) fexpr->args) ||
04524 contain_subplans((Node *) fexpr->args))
04525 return NULL;
04526
04527
04528 if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
04529 return NULL;
04530
04531
04532 if (FmgrHookIsNeeded(func_oid))
04533 return NULL;
04534
04535
04536
04537
04538 func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_oid));
04539 if (!HeapTupleIsValid(func_tuple))
04540 elog(ERROR, "cache lookup failed for function %u", func_oid);
04541 funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551 if (funcform->prolang != SQLlanguageId ||
04552 funcform->proisstrict ||
04553 funcform->provolatile == PROVOLATILE_VOLATILE ||
04554 funcform->prosecdef ||
04555 !funcform->proretset ||
04556 !heap_attisnull(func_tuple, Anum_pg_proc_proconfig))
04557 {
04558 ReleaseSysCache(func_tuple);
04559 return NULL;
04560 }
04561
04562
04563
04564
04565
04566 mycxt = AllocSetContextCreate(CurrentMemoryContext,
04567 "inline_set_returning_function",
04568 ALLOCSET_DEFAULT_MINSIZE,
04569 ALLOCSET_DEFAULT_INITSIZE,
04570 ALLOCSET_DEFAULT_MAXSIZE);
04571 oldcxt = MemoryContextSwitchTo(mycxt);
04572
04573
04574
04575
04576
04577
04578
04579
04580 saveInvalItems = root->glob->invalItems;
04581 root->glob->invalItems = NIL;
04582
04583
04584 tmp = SysCacheGetAttr(PROCOID,
04585 func_tuple,
04586 Anum_pg_proc_prosrc,
04587 &isNull);
04588 if (isNull)
04589 elog(ERROR, "null prosrc for function %u", func_oid);
04590 src = TextDatumGetCString(tmp);
04591
04592
04593
04594
04595
04596 callback_arg.proname = NameStr(funcform->proname);
04597 callback_arg.prosrc = src;
04598
04599 sqlerrcontext.callback = sql_inline_error_callback;
04600 sqlerrcontext.arg = (void *) &callback_arg;
04601 sqlerrcontext.previous = error_context_stack;
04602 error_context_stack = &sqlerrcontext;
04603
04604
04605
04606
04607
04608
04609
04610
04611 fexpr = (FuncExpr *) eval_const_expressions(root, (Node *) fexpr);
04612
04613
04614 if (!IsA(fexpr, FuncExpr) ||
04615 fexpr->funcid != func_oid)
04616 goto fail;
04617
04618
04619 if (list_length(fexpr->args) != funcform->pronargs)
04620 goto fail;
04621
04622
04623
04624
04625
04626
04627 pinfo = prepare_sql_fn_parse_info(func_tuple,
04628 (Node *) fexpr,
04629 fexpr->inputcollid);
04630
04631
04632
04633
04634
04635
04636 raw_parsetree_list = pg_parse_query(src);
04637 if (list_length(raw_parsetree_list) != 1)
04638 goto fail;
04639
04640 querytree_list = pg_analyze_and_rewrite_params(linitial(raw_parsetree_list),
04641 src,
04642 (ParserSetupHook) sql_fn_parser_setup,
04643 pinfo);
04644 if (list_length(querytree_list) != 1)
04645 goto fail;
04646 querytree = linitial(querytree_list);
04647
04648
04649
04650
04651 if (!IsA(querytree, Query) ||
04652 querytree->commandType != CMD_SELECT ||
04653 querytree->utilityStmt)
04654 goto fail;
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667 if (!check_sql_fn_retval(func_oid, fexpr->funcresulttype,
04668 querytree_list,
04669 &modifyTargetList, NULL) &&
04670 (get_typtype(fexpr->funcresulttype) == TYPTYPE_COMPOSITE ||
04671 fexpr->funcresulttype == RECORDOID))
04672 goto fail;
04673
04674
04675
04676
04677
04678
04679 if (modifyTargetList)
04680 goto fail;
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690 if (fexpr->funcresulttype == RECORDOID &&
04691 get_func_result_type(func_oid, NULL, NULL) == TYPEFUNC_RECORD &&
04692 !tlist_matches_coltypelist(querytree->targetList, rte->funccoltypes))
04693 goto fail;
04694
04695
04696
04697
04698 querytree = substitute_actual_srf_parameters(querytree,
04699 funcform->pronargs,
04700 fexpr->args);
04701
04702
04703
04704
04705
04706 MemoryContextSwitchTo(oldcxt);
04707
04708 querytree = copyObject(querytree);
04709
04710
04711 root->glob->invalItems = list_concat(saveInvalItems,
04712 copyObject(root->glob->invalItems));
04713
04714 MemoryContextDelete(mycxt);
04715 error_context_stack = sqlerrcontext.previous;
04716 ReleaseSysCache(func_tuple);
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726
04727 record_plan_function_dependency(root, func_oid);
04728
04729 return querytree;
04730
04731
04732 fail:
04733 MemoryContextSwitchTo(oldcxt);
04734 root->glob->invalItems = saveInvalItems;
04735 MemoryContextDelete(mycxt);
04736 error_context_stack = sqlerrcontext.previous;
04737 ReleaseSysCache(func_tuple);
04738
04739 return NULL;
04740 }
04741
04742
04743
04744
04745
04746
04747
04748 static Query *
04749 substitute_actual_srf_parameters(Query *expr, int nargs, List *args)
04750 {
04751 substitute_actual_srf_parameters_context context;
04752
04753 context.nargs = nargs;
04754 context.args = args;
04755 context.sublevels_up = 1;
04756
04757 return query_tree_mutator(expr,
04758 substitute_actual_srf_parameters_mutator,
04759 &context,
04760 0);
04761 }
04762
04763 static Node *
04764 substitute_actual_srf_parameters_mutator(Node *node,
04765 substitute_actual_srf_parameters_context *context)
04766 {
04767 Node *result;
04768
04769 if (node == NULL)
04770 return NULL;
04771 if (IsA(node, Query))
04772 {
04773 context->sublevels_up++;
04774 result = (Node *) query_tree_mutator((Query *) node,
04775 substitute_actual_srf_parameters_mutator,
04776 (void *) context,
04777 0);
04778 context->sublevels_up--;
04779 return result;
04780 }
04781 if (IsA(node, Param))
04782 {
04783 Param *param = (Param *) node;
04784
04785 if (param->paramkind == PARAM_EXTERN)
04786 {
04787 if (param->paramid <= 0 || param->paramid > context->nargs)
04788 elog(ERROR, "invalid paramid: %d", param->paramid);
04789
04790
04791
04792
04793
04794 result = copyObject(list_nth(context->args, param->paramid - 1));
04795 IncrementVarSublevelsUp(result, context->sublevels_up, 0);
04796 return result;
04797 }
04798 }
04799 return expression_tree_mutator(node,
04800 substitute_actual_srf_parameters_mutator,
04801 (void *) context);
04802 }
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816 static bool
04817 tlist_matches_coltypelist(List *tlist, List *coltypelist)
04818 {
04819 ListCell *tlistitem;
04820 ListCell *clistitem;
04821
04822 clistitem = list_head(coltypelist);
04823 foreach(tlistitem, tlist)
04824 {
04825 TargetEntry *tle = (TargetEntry *) lfirst(tlistitem);
04826 Oid coltype;
04827
04828 if (tle->resjunk)
04829 continue;
04830
04831 if (clistitem == NULL)
04832 return false;
04833
04834 coltype = lfirst_oid(clistitem);
04835 clistitem = lnext(clistitem);
04836
04837 if (exprType((Node *) tle->expr) != coltype)
04838 return false;
04839 }
04840
04841 if (clistitem != NULL)
04842 return false;
04843
04844 return true;
04845 }