diff options
author | Marc G. Fournier | 1998-09-04 12:52:23 +0000 |
---|---|---|
committer | Marc G. Fournier | 1998-09-04 12:52:23 +0000 |
commit | 370d6cdb64dfd571b9614263035f82eeb7a0aa1e (patch) | |
tree | c804567d4b16b9bc1eccf938b53d953014df4e50 | |
parent | e9d0fa3762fd3731117c5ba0fee719771aacfd98 (diff) |
From: David Hartwig <[email protected]>
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.
-rw-r--r-- | src/backend/optimizer/prep/prepkeyset.c | 110 |
1 files changed, 55 insertions, 55 deletions
diff --git a/src/backend/optimizer/prep/prepkeyset.c b/src/backend/optimizer/prep/prepkeyset.c index a8301a8f945..406c6929d0e 100644 --- a/src/backend/optimizer/prep/prepkeyset.c +++ b/src/backend/optimizer/prep/prepkeyset.c @@ -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); * * [email protected] 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); |