From: Tom Lane Date: Sun, 14 Feb 1999 22:24:25 +0000 (+0000) Subject: Fix optimizer coredump with unary-operator WHERE clauses. X-Git-Tag: REL9_0_0~25864 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=5500039843fa193f445f9e773889df2469590a1c;p=pg-rex%2Fsyncrep.git Fix optimizer coredump with unary-operator WHERE clauses. A test case is: create table linetab (x line); select * from linetab where ?| x; which coredumps in 6.4.2 and current sources. --- diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 26ca673359..d615d4e36d 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.29 1999/02/13 23:16:42 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.30 1999/02/14 22:24:25 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -101,7 +101,10 @@ make_opclause(Oper *op, Var *leftop, Var *rightop) expr->typeOid = InvalidOid; /* assume type checking done */ expr->opType = OP_EXPR; expr->oper = (Node *) op; - expr->args = makeList(leftop, rightop, -1); + if (rightop) + expr->args = lcons(leftop, lcons(rightop, NIL)); + else + expr->args = lcons(leftop, NIL); return expr; } @@ -125,7 +128,7 @@ get_leftop(Expr *clause) * get_rightop * * Returns the right operand in a clause of the form (op expr expr). - * + * NB: result will be NULL if applied to a unary op clause. */ Var * get_rightop(Expr *clause) @@ -470,6 +473,9 @@ is_joinable(Node *clause) leftop = (Node *) get_leftop((Expr *) clause); rightop = (Node *) get_rightop((Expr *) clause); + if (!rightop) + return false; /* unary opclauses need not apply */ + /* * One side of the clause (i.e. left or right operands) must either be * a var node ... @@ -491,19 +497,27 @@ is_joinable(Node *clause) * * Returns t iff 'clause' is a valid qualification clause. * + * For now we accept only "var op const" or "const op var". */ bool qual_clause_p(Node *clause) { + Node *leftop, + *rightop; + if (!is_opclause(clause)) return false; + leftop = (Node *) get_leftop((Expr *) clause); + rightop = (Node *) get_rightop((Expr *) clause); + + if (!rightop) + return false; /* unary opclauses need not apply */ + /* How about Param-s ? - vadim 02/03/98 */ - if (IsA(get_leftop((Expr *) clause), Var) && - IsA(get_rightop((Expr *) clause), Const)) + if (IsA(leftop, Var) && IsA(rightop, Const)) return true; - else if (IsA(get_rightop((Expr *) clause), Var) && - IsA(get_leftop((Expr *) clause), Const)) + if (IsA(rightop, Var) && IsA(leftop, Const)) return true; return false; } @@ -618,42 +632,35 @@ get_relattval(Node *clause, Datum *constval, int *flag) { - Var *left = get_leftop((Expr *) clause); - Var *right = get_rightop((Expr *) clause); + Var *left, + *right; - if (is_opclause(clause) && IsA(left, Var) && - IsA(right, Const)) - { + /* Careful; the passed clause might not be a binary operator at all */ - if (right != NULL) - { + if (!is_opclause(clause)) + goto default_results; - *relid = left->varno; - *attno = left->varattno; - *constval = ((Const *) right)->constvalue; - *flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_); + left = get_leftop((Expr *) clause); + right = get_rightop((Expr *) clause); - } - else - { + if (!right) + goto default_results; - *relid = left->varno; - *attno = left->varattno; - *constval = 0; - *flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_NOT_CONSTANT_); - - } + if (IsA(left, Var) && IsA(right, Const)) + { + *relid = left->varno; + *attno = left->varattno; + *constval = ((Const *) right)->constvalue; + *flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_); } - else if (is_opclause(clause) && IsA(left, Var) &&IsA(right, Param)) + else if (IsA(left, Var) && IsA(right, Param)) { *relid = left->varno; *attno = left->varattno; *constval = 0; *flag = (_SELEC_NOT_CONSTANT_); } - else if (is_opclause(clause) && - is_funcclause((Node *) left) && - IsA(right, Const)) + else if (is_funcclause((Node *) left) && IsA(right, Const)) { List *vars = pull_var_clause((Node *) left); @@ -662,52 +669,33 @@ get_relattval(Node *clause, *constval = ((Const *) right)->constvalue; *flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_); } - else if (is_opclause(clause) && - is_funcclause((Node *) right) && - IsA(left, Const)) + else if (IsA(right, Var) && IsA(left, Const)) { - List *vars = pull_var_clause((Node *) right); - - *relid = ((Var *) lfirst(vars))->varno; - *attno = InvalidAttrNumber; + *relid = right->varno; + *attno = right->varattno; *constval = ((Const *) left)->constvalue; *flag = (_SELEC_IS_CONSTANT_); - - } - else if (is_opclause(clause) && IsA(right, Var) && - IsA(left, Const)) - { - if (left != NULL) - { - - *relid = right->varno; - *attno = right->varattno; - *constval = ((Const *) left)->constvalue; - *flag = (_SELEC_IS_CONSTANT_); - } - else - { - - *relid = right->varno; - *attno = right->varattno; - *constval = 0; - *flag = (_SELEC_NOT_CONSTANT_); - } } - else if (is_opclause(clause) && IsA(right, Var) &&IsA(left, Param)) + else if (IsA(right, Var) &&IsA(left, Param)) { *relid = right->varno; *attno = right->varattno; *constval = 0; *flag = (_SELEC_NOT_CONSTANT_); } - else + else if (is_funcclause((Node *) right) && IsA(left, Const)) { + List *vars = pull_var_clause((Node *) right); - /* - * One or more of the operands are expressions (e.g., oper - * clauses) - */ + *relid = ((Var *) lfirst(vars))->varno; + *attno = InvalidAttrNumber; + *constval = ((Const *) left)->constvalue; + *flag = (_SELEC_IS_CONSTANT_); + } + else + { + /* Duh, it's too complicated for me... */ +default_results: *relid = _SELEC_VALUE_UNKNOWN_; *attno = _SELEC_VALUE_UNKNOWN_; *constval = 0; @@ -733,43 +721,47 @@ get_rels_atts(Node *clause, int *relid2, AttrNumber *attno2) { - Var *left = get_leftop((Expr *) clause); - Var *right = get_rightop((Expr *) clause); - bool var_left = (IsA(left, Var)); - bool var_right = (IsA(right, Var)); - bool varexpr_left = (bool) ((IsA(left, Func) ||IsA(left, Oper)) && - contain_var_clause((Node *) left)); - bool varexpr_right = (bool) ((IsA(right, Func) ||IsA(right, Oper)) && - contain_var_clause((Node *) right)); - if (is_opclause(clause)) { - if (var_left && var_right) - { + Var *left = get_leftop((Expr *) clause); + Var *right = get_rightop((Expr *) clause); - *relid1 = left->varno; - *attno1 = left->varoattno; - *relid2 = right->varno; - *attno2 = right->varoattno; - return; - } - else if (var_left && varexpr_right) - { - - *relid1 = left->varno; - *attno1 = left->varoattno; - *relid2 = _SELEC_VALUE_UNKNOWN_; - *attno2 = _SELEC_VALUE_UNKNOWN_; - return; - } - else if (varexpr_left && var_right) + if (left && right) { + bool var_left = IsA(left, Var); + bool var_right = IsA(right, Var); + bool varexpr_left = (bool) ((IsA(left, Func) || IsA(left, Oper)) && + contain_var_clause((Node *) left)); + bool varexpr_right = (bool) ((IsA(right, Func) || IsA(right, Oper)) && + contain_var_clause((Node *) right)); - *relid1 = _SELEC_VALUE_UNKNOWN_; - *attno1 = _SELEC_VALUE_UNKNOWN_; - *relid2 = right->varno; - *attno2 = right->varoattno; - return; + if (var_left && var_right) + { + + *relid1 = left->varno; + *attno1 = left->varoattno; + *relid2 = right->varno; + *attno2 = right->varoattno; + return; + } + if (var_left && varexpr_right) + { + + *relid1 = left->varno; + *attno1 = left->varoattno; + *relid2 = _SELEC_VALUE_UNKNOWN_; + *attno2 = _SELEC_VALUE_UNKNOWN_; + return; + } + if (varexpr_left && var_right) + { + + *relid1 = _SELEC_VALUE_UNKNOWN_; + *attno1 = _SELEC_VALUE_UNKNOWN_; + *relid2 = right->varno; + *attno2 = right->varoattno; + return; + } } } @@ -777,7 +769,6 @@ get_rels_atts(Node *clause, *attno1 = _SELEC_VALUE_UNKNOWN_; *relid2 = _SELEC_VALUE_UNKNOWN_; *attno2 = _SELEC_VALUE_UNKNOWN_; - return; } void @@ -813,4 +804,3 @@ CommuteClause(Node *clause) lfirst(((Expr *) clause)->args) = lsecond(((Expr *) clause)->args); lsecond(((Expr *) clause)->args) = temp; } -