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);