Clean up prepkeyset.c - Mailing list pgsql-hackers

From David Hartwig
Subject Clean up prepkeyset.c
Date
Msg-id 35EF3CCE.30456BE5@bellatlantic.net
Whole thread Raw
List pgsql-hackers
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.
*** ./backend/optimizer/prep/prepkeyset.c.orig    Thu Sep  3 16:17:56 1998
--- ./backend/optimizer/prep/prepkeyset.c    Thu Sep  3 20:17:05 1998
***************
*** 11,45 ****
  #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);

  /**********************************************************************
   *   This routine transforms query trees with the following form:
--- 11,30 ----
  #include <string.h>

  #include "postgres.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)

  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,80 ****
   *
   *        daveh@insightdist.com   1998-08-31
   *
!  *   Needs to better identify the signeture WHERE clause.
!  *   May want to also prune out duplicate where clauses.
   **********************************************************************/
  void
  transformKeySetQuery(Query *origNode)
--- 58,64 ----
   *
   *        daveh@insightdist.com   1998-08-31
   *
!  *   May want to also prune out duplicate terms.
   **********************************************************************/
  void
  transformKeySetQuery(Query *origNode)
***************
*** 92,109 ****
          return;

      /*  Qualify single table query   */

      /*  Qualify where clause */
!     if  ( ! inspectOrNode((Expr*)origNode->qual))  {
          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);

--- 76,95 ----
          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) || TotalExpr < 9)
          return;

      /*  Copy essential elements into a union node */
      while (((Expr*)origNode->qual)->opType == OR_EXPR)  {
          Query       *unionNode = makeNode(Query);

***************
*** 113,123 ****
          /*   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;
--- 99,104 ----
***************
*** 139,147 ****


  static int
  inspectOrNode(Expr *expr)
  {
!     int fr = 0, sr = 0;
      Expr *firstExpr, *secondExpr;

      if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == OR_EXPR))
--- 120,133 ----


  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 rc;
      Expr *firstExpr, *secondExpr;

      if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == OR_EXPR))
***************
*** 152,178 ****
      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 (secondExpr->opType == AND_EXPR)
!         sr = inspectAndNode(secondExpr);
!     else if (secondExpr->opType == OP_EXPR)
!         sr = inspectOpNode(secondExpr);

!     return (fr && sr);
  }


  static int
  inspectAndNode(Expr *expr)
  {
!     int fr = 0, sr = 0;
      Expr *firstExpr, *secondExpr;

      if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == AND_EXPR))
--- 138,172 ----
      if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
          return 0;

!     if (firstExpr->opType == OR_EXPR && secondExpr->opType == AND_EXPR)
!     {
!         if ((rc = inspectOrNode(firstExpr)) == 0)
!             return 0;

!         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 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 rc;
      Expr *firstExpr, *secondExpr;

      if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == AND_EXPR))
***************
*** 183,197 ****
      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 (secondExpr->opType == OP_EXPR)
!         sr = inspectOpNode(secondExpr);
!
!     return (fr && sr);
  }


--- 177,195 ----
      if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
          return 0;

!     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;
!     }

!     return 0;
  }


***************
*** 205,211 ****
      Expr *firstExpr, *secondExpr;

      if (nodeTag(expr) != T_Expr || expr->opType != OP_EXPR)
!         return 0;

      firstExpr = lfirst(expr->args);
      secondExpr = lsecond(expr->args);
--- 203,211 ----
      Expr *firstExpr, *secondExpr;

      if (nodeTag(expr) != T_Expr || expr->opType != OP_EXPR)
!         return FALSE;
!
!     TotalExpr++;

      firstExpr = lfirst(expr->args);
      secondExpr = lsecond(expr->args);

pgsql-hackers by date:

Previous
From: Vadim Mikheev
Date:
Subject: Re: [HACKERS] Open 6.4 items
Next
From: Aleksey Dashevsky
Date:
Subject: Subqueries?