OSDN Git Service

From: David Hartwig <daybee@bellatlantic.net>
authorMarc G. Fournier <scrappy@hub.org>
Fri, 4 Sep 1998 12:52:23 +0000 (12:52 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Fri, 4 Sep 1998 12:52:23 +0000 (12:52 +0000)
I put some extra checks to make sure a query was a good candidate for
rewrite into a UNION.    Besides the existing checks:

1.  Make sure the AND/OR tree was rectangular.  ( i.e.    3 X 4  or 10 X
3)
2.  Only one table.
3.  Must have an AND dimension.
4.  At least 9 OP expressions total

Also  cleaned up and commented.

src/backend/optimizer/prep/prepkeyset.c

index a8301a8..406c692 100644 (file)
 #include <string.h>
 
 #include "postgres.h"
-#include "nodes/pg_list.h"
-#include "nodes/parsenodes.h"
-#include "utils/elog.h"
-
-#include "nodes/nodes.h"
-#include "nodes/execnodes.h"
-#include "nodes/plannodes.h"
-#include "nodes/primnodes.h"
-#include "nodes/relation.h"
-
-#include "catalog/pg_type.h"
-#include "lib/stringinfo.h"
 #include "optimizer/planmain.h"
+
 /*
  * Node_Copy--
  *        a macro to simplify calling of copyObject on the specified field
  */
 #define Node_Copy(from, newnode, field) newnode->field = copyObject(from->field)
 
-/*****  DEBUG stuff
-#define TABS {int i; printf("\n"); for (i = 0; i<level; i++) printf("\t"); }
-static int level = 0;
-******/
-
 bool _use_keyset_query_optimizer = FALSE;
 
 static int inspectOpNode(Expr *expr);
 static int inspectAndNode(Expr *expr);
 static int inspectOrNode(Expr *expr);
+static int TotalExpr;
 
 /**********************************************************************
  *   This routine transforms query trees with the following form:
@@ -73,8 +58,7 @@ static int inspectOrNode(Expr *expr);
  *
  *        daveh@insightdist.com   1998-08-31
  *
- *   Needs to better identify the signeture WHERE clause.
- *   May want to also prune out duplicate where clauses.
+ *   May want to also prune out duplicate terms.
  **********************************************************************/
 void
 transformKeySetQuery(Query *origNode)
@@ -92,18 +76,20 @@ transformKeySetQuery(Query *origNode)
                return;
 
        /*  Qualify single table query   */
-
+       if (length(origNode->rtable) != 1)
+                       return;
+
+       /*  Sorry about the global, not worth passing around     */
+       /*  9 expressions seems like a good number.  More than 9 */
+    /*  and it starts to slow down quite a bit               */
+     TotalExpr = 0; 
+    /*************************/
        /*  Qualify where clause */
-       if  ( ! inspectOrNode((Expr*)origNode->qual))  {
+    /*************************/
+       if  ( ! inspectOrNode((Expr*)origNode->qual) || TotalExpr < 9)
                return;
-       }
 
        /*  Copy essential elements into a union node */
-       /*  
-       elog(NOTICE, "OR_EXPR=%d, OP_EXPR=%d, AND_EXPR=%d", OR_EXPR, OP_EXPR, AND_EXPR);
-       elog(NOTICE, "T_List=%d, T_Expr=%d, T_Var=%d, T_Const=%d", T_List, T_Expr, T_Var, T_Const);
-       elog(NOTICE, "opType=%d", ((Expr*)origNode->qual)->opType);
-       */
        while (((Expr*)origNode->qual)->opType == OR_EXPR)  {
                Query      *unionNode = makeNode(Query);
 
@@ -113,11 +99,6 @@ transformKeySetQuery(Query *origNode)
                /*   Pull up balance of tree  */
                origNode->qual = lfirst(((Expr*)origNode->qual)->args);  
 
-               /*
-               elog(NOTICE, "origNode: opType=%d, nodeTag=%d", ((Expr*)origNode->qual)->opType, nodeTag(origNode->qual));
-               elog(NOTICE, "unionNode: opType=%d, nodeTag=%d", ((Expr*)unionNode->qual)->opType, nodeTag(unionNode->qual));
-               */
-
                unionNode->commandType = origNode->commandType;
                unionNode->resultRelation = origNode->resultRelation;
                unionNode->isPortal = origNode->isPortal;
@@ -139,9 +120,14 @@ transformKeySetQuery(Query *origNode)
 
 
 static int
+/**********************************************************************
+ *   Checks for 1 or more OR terms w/ 1 or more AND terms.
+ *   AND terms must be equal in size.
+ *   Returns the number of each AND term.
+ **********************************************************************/
 inspectOrNode(Expr *expr)
 {
-       int fr = 0, sr = 0;
+       int rc;
        Expr *firstExpr, *secondExpr;
 
        if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == OR_EXPR))
@@ -152,27 +138,35 @@ inspectOrNode(Expr *expr)
        if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr) 
                return 0;
 
-       if (firstExpr->opType == OR_EXPR)
-               fr = inspectOrNode(firstExpr);
-       else if (firstExpr->opType == OP_EXPR)    /*   Need to make sure it is last  */
-               fr = inspectOpNode(firstExpr);
-       else if (firstExpr->opType == AND_EXPR)    /*   Need to make sure it is last  */
-               fr = inspectAndNode(firstExpr);
-
+       if (firstExpr->opType == OR_EXPR && secondExpr->opType == AND_EXPR)
+       {
+               if ((rc = inspectOrNode(firstExpr)) == 0) 
+                       return 0;
 
-       if (secondExpr->opType == AND_EXPR)
-               sr = inspectAndNode(secondExpr);
-       else if (secondExpr->opType == OP_EXPR)
-               sr = inspectOpNode(secondExpr);
+               return (rc == inspectAndNode(secondExpr)) ? rc : 0; 
+       }
+       else if (firstExpr->opType == AND_EXPR && secondExpr->opType == AND_EXPR)
+       {
+               if ((rc = inspectAndNode(firstExpr)) == 0) 
+                       return 0;
+               
+               return (rc == inspectAndNode(secondExpr)) ? rc : 0; 
                
-       return (fr && sr);              
+       }
+
+       return 0;
 }
 
 
 static int
+/**********************************************************************
+ *  Check for one or more AND terms.   Each sub-term must be a T_Const
+ *  T_Var expression.   
+ *  Returns the number of AND terms.
+ **********************************************************************/
 inspectAndNode(Expr *expr)
 {
-       int fr = 0, sr = 0;
+       int rc;
        Expr *firstExpr, *secondExpr;
 
        if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == AND_EXPR))
@@ -183,15 +177,19 @@ inspectAndNode(Expr *expr)
        if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr) 
                return 0;
 
-       if (firstExpr->opType == AND_EXPR)
-               fr = inspectAndNode(firstExpr);
-       else if (firstExpr->opType == OP_EXPR)
-               fr = inspectOpNode(firstExpr);
+       if (firstExpr->opType == AND_EXPR &&
+                       secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
+       {
+               rc =  inspectAndNode(firstExpr);
+               return ((rc) ? (rc + 1) : 0);   /*  Add up the AND nodes */
+       }
+       else if (firstExpr->opType == OP_EXPR && inspectOpNode(firstExpr) && 
+                       secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
+       {
+               return 1;
+       }
 
-       if (secondExpr->opType == OP_EXPR)
-               sr = inspectOpNode(secondExpr);
-               
-       return (fr && sr);              
+       return 0;
 }
 
 
@@ -205,7 +203,9 @@ inspectOpNode(Expr *expr)
        Expr *firstExpr, *secondExpr;
 
        if (nodeTag(expr) != T_Expr || expr->opType != OP_EXPR)
-               return 0;
+               return FALSE;
+
+       TotalExpr++;
 
        firstExpr = lfirst(expr->args);
        secondExpr = lsecond(expr->args);