~ubuntu-branches/ubuntu/natty/postgresql-8.4/natty-security

« back to all changes in this revision

Viewing changes to src/backend/optimizer/util/clauses.c

Tags: upstream-8.4.0
ImportĀ upstreamĀ versionĀ 8.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 *
9
9
 *
10
10
 * IDENTIFICATION
11
 
 *        $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.276 2009/02/25 03:30:37 tgl Exp $
 
11
 *        $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.277 2009/06/11 14:48:59 momjian Exp $
12
12
 *
13
13
 * HISTORY
14
14
 *        AUTHOR                        DATE                    MAJOR EVENT
98
98
                                  bool allow_inline,
99
99
                                  eval_const_expressions_context *context);
100
100
static List *add_function_defaults(List *args, Oid result_type,
101
 
                                                                   HeapTuple func_tuple,
102
 
                                                                   eval_const_expressions_context *context);
 
101
                                          HeapTuple func_tuple,
 
102
                                          eval_const_expressions_context *context);
103
103
static Expr *evaluate_function(Oid funcid,
104
104
                                  Oid result_type, int32 result_typmod, List *args,
105
105
                                  HeapTuple func_tuple,
114
114
static void sql_inline_error_callback(void *arg);
115
115
static Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod);
116
116
static Query *substitute_actual_srf_parameters(Query *expr,
117
 
                                                                                           int nargs, List *args);
 
117
                                                                 int nargs, List *args);
118
118
static Node *substitute_actual_srf_parameters_mutator(Node *node,
119
 
                                                        substitute_actual_srf_parameters_context *context);
 
119
                                                  substitute_actual_srf_parameters_context *context);
120
120
static bool tlist_matches_coltypelist(List *tlist, List *coltypelist);
121
121
 
122
122
 
612
612
                lists->numWindowFuncs++;
613
613
 
614
614
                /*
615
 
                 * Complain if the window function's arguments contain window functions
 
615
                 * Complain if the window function's arguments contain window
 
616
                 * functions
616
617
                 */
617
618
                if (contain_window_function((Node *) wfunc->args))
618
619
                        ereport(ERROR,
1557
1558
 
1558
1559
                /*
1559
1560
                 * We don't bother considering the OR case, because it's fairly
1560
 
                 * unlikely anyone would write "v1 IS NULL OR v1 IS NULL".
1561
 
                 * Likewise, the NOT case isn't worth expending code on.
 
1561
                 * unlikely anyone would write "v1 IS NULL OR v1 IS NULL". Likewise,
 
1562
                 * the NOT case isn't worth expending code on.
1562
1563
                 */
1563
1564
                if (expr->boolop == AND_EXPR)
1564
1565
                {
1594
1595
 
1595
1596
                if (expr->nulltesttype == IS_NULL)
1596
1597
                {
1597
 
                        Var        *var = (Var *) expr->arg;
 
1598
                        Var                *var = (Var *) expr->arg;
1598
1599
 
1599
1600
                        if (var && IsA(var, Var) &&
1600
1601
                                var->varlevelsup == 0)
1608
1609
 
1609
1610
                if (expr->booltesttype == IS_UNKNOWN)
1610
1611
                {
1611
 
                        Var        *var = (Var *) expr->arg;
 
1612
                        Var                *var = (Var *) expr->arg;
1612
1613
 
1613
1614
                        if (var && IsA(var, Var) &&
1614
1615
                                var->varlevelsup == 0)
2013
2014
        if (root)
2014
2015
        {
2015
2016
                context.boundParams = root->glob->boundParams;  /* bound Params */
2016
 
                context.glob = root->glob; /* for inlined-function dependencies */
 
2017
                context.glob = root->glob;              /* for inlined-function dependencies */
2017
2018
        }
2018
2019
        else
2019
2020
        {
2453
2454
 
2454
2455
                /*
2455
2456
                 * CoerceViaIO represents calling the source type's output function
2456
 
                 * then the result type's input function.  So, try to simplify it
2457
 
                 * as though it were a stack of two such function calls.  First we
2458
 
                 * need to know what the functions are.
 
2457
                 * then the result type's input function.  So, try to simplify it as
 
2458
                 * though it were a stack of two such function calls.  First we need
 
2459
                 * to know what the functions are.
2459
2460
                 */
2460
2461
                getTypeOutputInfo(exprType((Node *) arg), &outfunc, &outtypisvarlena);
2461
2462
                getTypeInputInfo(expr->resulttype, &infunc, &intypioparam);
2505
2506
                ArrayCoerceExpr *newexpr;
2506
2507
 
2507
2508
                /*
2508
 
                 * Reduce constants in the ArrayCoerceExpr's argument, then build
2509
 
                 * a new ArrayCoerceExpr.
 
2509
                 * Reduce constants in the ArrayCoerceExpr's argument, then build a
 
2510
                 * new ArrayCoerceExpr.
2510
2511
                 */
2511
2512
                arg = (Expr *) eval_const_expressions_mutator((Node *) expr->arg,
2512
2513
                                                                                                          context);
2925
2926
                newbtest->booltesttype = btest->booltesttype;
2926
2927
                return (Node *) newbtest;
2927
2928
        }
2928
 
        if (IsA(node, PlaceHolderVar) && context->estimate)
 
2929
        if (IsA(node, PlaceHolderVar) &&context->estimate)
2929
2930
        {
2930
2931
                /*
2931
2932
                 * In estimation mode, just strip the PlaceHolderVar node altogether;
3266
3267
 *
3267
3268
 * It is possible for some of the defaulted arguments to be polymorphic;
3268
3269
 * therefore we can't assume that the default expressions have the correct
3269
 
 * data types already.  We have to re-resolve polymorphics and do coercion
 
3270
 * data types already.  We have to re-resolve polymorphics and do coercion
3270
3271
 * just like the parser did.
3271
3272
 */
3272
3273
static List *
3594
3595
        /*
3595
3596
         * Make sure the function (still) returns what it's declared to.  This
3596
3597
         * will raise an error if wrong, but that's okay since the function would
3597
 
         * fail at runtime anyway.  Note that check_sql_fn_retval will also insert
 
3598
         * fail at runtime anyway.      Note that check_sql_fn_retval will also insert
3598
3599
         * a RelabelType if needed to make the tlist expression match the declared
3599
3600
         * type of the function.
3600
3601
         *
3695
3696
        MemoryContextDelete(mycxt);
3696
3697
 
3697
3698
        /*
3698
 
         * Since there is now no trace of the function in the plan tree, we
3699
 
         * must explicitly record the plan's dependency on the function.
 
3699
         * Since there is now no trace of the function in the plan tree, we must
 
3700
         * explicitly record the plan's dependency on the function.
3700
3701
         */
3701
3702
        if (context->glob)
3702
3703
                record_plan_function_dependency(context->glob, funcid);
3825
3826
        fix_opfuncids((Node *) expr);
3826
3827
 
3827
3828
        /*
3828
 
         * Prepare expr for execution.  (Note: we can't use ExecPrepareExpr
 
3829
         * Prepare expr for execution.  (Note: we can't use ExecPrepareExpr
3829
3830
         * because it'd result in recursively invoking eval_const_expressions.)
3830
3831
         */
3831
3832
        exprstate = ExecInitExpr(expr, NULL);
3908
3909
        Assert(rte->rtekind == RTE_FUNCTION);
3909
3910
 
3910
3911
        /*
3911
 
         * It doesn't make a lot of sense for a SQL SRF to refer to itself
3912
 
         * in its own FROM clause, since that must cause infinite recursion
3913
 
         * at runtime.  It will cause this code to recurse too, so check
3914
 
         * for stack overflow.  (There's no need to do more.)
 
3912
         * It doesn't make a lot of sense for a SQL SRF to refer to itself in its
 
3913
         * own FROM clause, since that must cause infinite recursion at runtime.
 
3914
         * It will cause this code to recurse too, so check for stack overflow.
 
3915
         * (There's no need to do more.)
3915
3916
         */
3916
3917
        check_stack_depth();
3917
3918
 
3922
3923
 
3923
3924
        /*
3924
3925
         * The function must be declared to return a set, else inlining would
3925
 
         * change the results if the contained SELECT didn't return exactly
3926
 
         * one row.
 
3926
         * change the results if the contained SELECT didn't return exactly one
 
3927
         * row.
3927
3928
         */
3928
3929
        if (!fexpr->funcretset)
3929
3930
                return NULL;
3932
3933
         * Refuse to inline if the arguments contain any volatile functions or
3933
3934
         * sub-selects.  Volatile functions are rejected because inlining may
3934
3935
         * result in the arguments being evaluated multiple times, risking a
3935
 
         * change in behavior.  Sub-selects are rejected partly for implementation
 
3936
         * change in behavior.  Sub-selects are rejected partly for implementation
3936
3937
         * reasons (pushing them down another level might change their behavior)
3937
3938
         * and partly because they're likely to be expensive and so multiple
3938
3939
         * evaluation would be bad.
3957
3958
 
3958
3959
        /*
3959
3960
         * Forget it if the function is not SQL-language or has other showstopper
3960
 
         * properties.  In particular it mustn't be declared STRICT, since we
 
3961
         * properties.  In particular it mustn't be declared STRICT, since we
3961
3962
         * couldn't enforce that.  It also mustn't be VOLATILE, because that is
3962
3963
         * supposed to cause it to be executed with its own snapshot, rather than
3963
3964
         * sharing the snapshot of the calling query.  (The nargs check is just
4017
4018
        src = TextDatumGetCString(tmp);
4018
4019
 
4019
4020
        /*
4020
 
         * Parse, analyze, and rewrite (unlike inline_function(), we can't
4021
 
         * skip rewriting here).  We can fail as soon as we find more than
4022
 
         * one query, though.
 
4021
         * Parse, analyze, and rewrite (unlike inline_function(), we can't skip
 
4022
         * rewriting here).  We can fail as soon as we find more than one query,
 
4023
         * though.
4023
4024
         */
4024
4025
        raw_parsetree_list = pg_parse_query(src);
4025
4026
        if (list_length(raw_parsetree_list) != 1)
4026
4027
                goto fail;
4027
4028
 
4028
4029
        querytree_list = pg_analyze_and_rewrite(linitial(raw_parsetree_list), src,
4029
 
                                                          argtypes, funcform->pronargs);
 
4030
                                                                                        argtypes, funcform->pronargs);
4030
4031
        if (list_length(querytree_list) != 1)
4031
4032
                goto fail;
4032
4033
        querytree = linitial(querytree_list);
4043
4044
        /*
4044
4045
         * Make sure the function (still) returns what it's declared to.  This
4045
4046
         * will raise an error if wrong, but that's okay since the function would
4046
 
         * fail at runtime anyway.  Note that check_sql_fn_retval will also insert
 
4047
         * fail at runtime anyway.      Note that check_sql_fn_retval will also insert
4047
4048
         * RelabelType(s) if needed to make the tlist expression(s) match the
4048
4049
         * declared type of the function.
4049
4050
         *
4050
 
         * If the function returns a composite type, don't inline unless the
4051
 
         * check shows it's returning a whole tuple result; otherwise what
4052
 
         * it's returning is a single composite column which is not what we need.
 
4051
         * If the function returns a composite type, don't inline unless the check
 
4052
         * shows it's returning a whole tuple result; otherwise what it's
 
4053
         * returning is a single composite column which is not what we need.
4053
4054
         */
4054
4055
        if (!check_sql_fn_retval(fexpr->funcid, fexpr->funcresulttype,
4055
4056
                                                         querytree_list,
4076
4077
                                                                                                 fexpr->args);
4077
4078
 
4078
4079
        /*
4079
 
         * Copy the modified query out of the temporary memory context,
4080
 
         * and clean up.
 
4080
         * Copy the modified query out of the temporary memory context, and clean
 
4081
         * up.
4081
4082
         */
4082
4083
        MemoryContextSwitchTo(oldcxt);
4083
4084
 
4088
4089
        ReleaseSysCache(func_tuple);
4089
4090
 
4090
4091
        /*
4091
 
         * Since there is now no trace of the function in the plan tree, we
4092
 
         * must explicitly record the plan's dependency on the function.
 
4092
         * Since there is now no trace of the function in the plan tree, we must
 
4093
         * explicitly record the plan's dependency on the function.
4093
4094
         */
4094
4095
        record_plan_function_dependency(root->glob, fexpr->funcid);
4095
4096
 
4128
4129
 
4129
4130
static Node *
4130
4131
substitute_actual_srf_parameters_mutator(Node *node,
4131
 
                                                        substitute_actual_srf_parameters_context *context)
 
4132
                                                   substitute_actual_srf_parameters_context *context)
4132
4133
{
4133
 
        Node   *result;
 
4134
        Node       *result;
4134
4135
 
4135
4136
        if (node == NULL)
4136
4137
                return NULL;
4138
4139
        {
4139
4140
                context->sublevels_up++;
4140
4141
                result = (Node *) query_tree_mutator((Query *) node,
4141
 
                                                                          substitute_actual_srf_parameters_mutator,
 
4142
                                                                        substitute_actual_srf_parameters_mutator,
4142
4143
                                                                                         (void *) context,
4143
4144
                                                                                         0);
4144
4145
                context->sublevels_up--;
4154
4155
                                elog(ERROR, "invalid paramid: %d", param->paramid);
4155
4156
 
4156
4157
                        /*
4157
 
                         * Since the parameter is being inserted into a subquery,
4158
 
                         * we must adjust levels.
 
4158
                         * Since the parameter is being inserted into a subquery, we must
 
4159
                         * adjust levels.
4159
4160
                         */
4160
4161
                        result = copyObject(list_nth(context->args, param->paramid - 1));
4161
4162
                        IncrementVarSublevelsUp(result, context->sublevels_up, 0);