From: David Hartwig <daybee@bellatlantic.net>
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.
This commit is contained in:
parent
e9d0fa3762
commit
370d6cdb64
|
@ -11,35 +11,20 @@
|
|||
#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 (fr && sr);
|
||||
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 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);
|
||||
|
|
Loading…
Reference in New Issue