Fix optimizer coredump with unary-operator WHERE clauses.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Feb 1999 22:24:25 +0000 (22:24 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Feb 1999 22:24:25 +0000 (22:24 +0000)
A test case is:
create table linetab (x line);
select * from linetab where ?| x;
which coredumps in 6.4.2 and current sources.

src/backend/optimizer/util/clauses.c

index 26ca67335906a21715ba90c50161fcef5a68950e..d615d4e36d6ac2649068c19aa3f252b99d5566b7 100644 (file)
@@ -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;
 }
-