Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 370d6cd

Browse files
committed
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.
1 parent e9d0fa3 commit 370d6cd

File tree

1 file changed

+55
-55
lines changed

1 file changed

+55
-55
lines changed

src/backend/optimizer/prep/prepkeyset.c

+55-55
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,20 @@
1111
#include <string.h>
1212

1313
#include "postgres.h"
14-
#include "nodes/pg_list.h"
15-
#include "nodes/parsenodes.h"
16-
#include "utils/elog.h"
17-
18-
#include "nodes/nodes.h"
19-
#include "nodes/execnodes.h"
20-
#include "nodes/plannodes.h"
21-
#include "nodes/primnodes.h"
22-
#include "nodes/relation.h"
23-
24-
#include "catalog/pg_type.h"
25-
#include "lib/stringinfo.h"
2614
#include "optimizer/planmain.h"
15+
2716
/*
2817
* Node_Copy--
2918
* a macro to simplify calling of copyObject on the specified field
3019
*/
3120
#define Node_Copy(from, newnode, field) newnode->field = copyObject(from->field)
3221

33-
/***** DEBUG stuff
34-
#define TABS {int i; printf("\n"); for (i = 0; i<level; i++) printf("\t"); }
35-
static int level = 0;
36-
******/
37-
3822
bool _use_keyset_query_optimizer = FALSE;
3923

4024
static int inspectOpNode(Expr *expr);
4125
static int inspectAndNode(Expr *expr);
4226
static int inspectOrNode(Expr *expr);
27+
static int TotalExpr;
4328

4429
/**********************************************************************
4530
* This routine transforms query trees with the following form:
@@ -73,8 +58,7 @@ static int inspectOrNode(Expr *expr);
7358
*
7459
* daveh@insightdist.com 1998-08-31
7560
*
76-
* Needs to better identify the signeture WHERE clause.
77-
* May want to also prune out duplicate where clauses.
61+
* May want to also prune out duplicate terms.
7862
**********************************************************************/
7963
void
8064
transformKeySetQuery(Query *origNode)
@@ -92,18 +76,20 @@ transformKeySetQuery(Query *origNode)
9276
return;
9377

9478
/* Qualify single table query */
95-
79+
if (length(origNode->rtable) != 1)
80+
return;
81+
82+
/* Sorry about the global, not worth passing around */
83+
/* 9 expressions seems like a good number. More than 9 */
84+
/* and it starts to slow down quite a bit */
85+
TotalExpr = 0;
86+
/*************************/
9687
/* Qualify where clause */
97-
if ( ! inspectOrNode((Expr*)origNode->qual)) {
88+
/*************************/
89+
if ( ! inspectOrNode((Expr*)origNode->qual) || TotalExpr < 9)
9890
return;
99-
}
10091

10192
/* Copy essential elements into a union node */
102-
/*
103-
elog(NOTICE, "OR_EXPR=%d, OP_EXPR=%d, AND_EXPR=%d", OR_EXPR, OP_EXPR, AND_EXPR);
104-
elog(NOTICE, "T_List=%d, T_Expr=%d, T_Var=%d, T_Const=%d", T_List, T_Expr, T_Var, T_Const);
105-
elog(NOTICE, "opType=%d", ((Expr*)origNode->qual)->opType);
106-
*/
10793
while (((Expr*)origNode->qual)->opType == OR_EXPR) {
10894
Query *unionNode = makeNode(Query);
10995

@@ -113,11 +99,6 @@ transformKeySetQuery(Query *origNode)
11399
/* Pull up balance of tree */
114100
origNode->qual = lfirst(((Expr*)origNode->qual)->args);
115101

116-
/*
117-
elog(NOTICE, "origNode: opType=%d, nodeTag=%d", ((Expr*)origNode->qual)->opType, nodeTag(origNode->qual));
118-
elog(NOTICE, "unionNode: opType=%d, nodeTag=%d", ((Expr*)unionNode->qual)->opType, nodeTag(unionNode->qual));
119-
*/
120-
121102
unionNode->commandType = origNode->commandType;
122103
unionNode->resultRelation = origNode->resultRelation;
123104
unionNode->isPortal = origNode->isPortal;
@@ -139,9 +120,14 @@ transformKeySetQuery(Query *origNode)
139120

140121

141122
static int
123+
/**********************************************************************
124+
* Checks for 1 or more OR terms w/ 1 or more AND terms.
125+
* AND terms must be equal in size.
126+
* Returns the number of each AND term.
127+
**********************************************************************/
142128
inspectOrNode(Expr *expr)
143129
{
144-
int fr = 0, sr = 0;
130+
int rc;
145131
Expr *firstExpr, *secondExpr;
146132

147133
if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == OR_EXPR))
@@ -152,27 +138,35 @@ inspectOrNode(Expr *expr)
152138
if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
153139
return 0;
154140

155-
if (firstExpr->opType == OR_EXPR)
156-
fr = inspectOrNode(firstExpr);
157-
else if (firstExpr->opType == OP_EXPR) /* Need to make sure it is last */
158-
fr = inspectOpNode(firstExpr);
159-
else if (firstExpr->opType == AND_EXPR) /* Need to make sure it is last */
160-
fr = inspectAndNode(firstExpr);
161-
141+
if (firstExpr->opType == OR_EXPR && secondExpr->opType == AND_EXPR)
142+
{
143+
if ((rc = inspectOrNode(firstExpr)) == 0)
144+
return 0;
162145

163-
if (secondExpr->opType == AND_EXPR)
164-
sr = inspectAndNode(secondExpr);
165-
else if (secondExpr->opType == OP_EXPR)
166-
sr = inspectOpNode(secondExpr);
146+
return (rc == inspectAndNode(secondExpr)) ? rc : 0;
147+
}
148+
else if (firstExpr->opType == AND_EXPR && secondExpr->opType == AND_EXPR)
149+
{
150+
if ((rc = inspectAndNode(firstExpr)) == 0)
151+
return 0;
152+
153+
return (rc == inspectAndNode(secondExpr)) ? rc : 0;
167154

168-
return (fr && sr);
155+
}
156+
157+
return 0;
169158
}
170159

171160

172161
static int
162+
/**********************************************************************
163+
* Check for one or more AND terms. Each sub-term must be a T_Const
164+
* T_Var expression.
165+
* Returns the number of AND terms.
166+
**********************************************************************/
173167
inspectAndNode(Expr *expr)
174168
{
175-
int fr = 0, sr = 0;
169+
int rc;
176170
Expr *firstExpr, *secondExpr;
177171

178172
if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == AND_EXPR))
@@ -183,15 +177,19 @@ inspectAndNode(Expr *expr)
183177
if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
184178
return 0;
185179

186-
if (firstExpr->opType == AND_EXPR)
187-
fr = inspectAndNode(firstExpr);
188-
else if (firstExpr->opType == OP_EXPR)
189-
fr = inspectOpNode(firstExpr);
180+
if (firstExpr->opType == AND_EXPR &&
181+
secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
182+
{
183+
rc = inspectAndNode(firstExpr);
184+
return ((rc) ? (rc + 1) : 0); /* Add up the AND nodes */
185+
}
186+
else if (firstExpr->opType == OP_EXPR && inspectOpNode(firstExpr) &&
187+
secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
188+
{
189+
return 1;
190+
}
190191

191-
if (secondExpr->opType == OP_EXPR)
192-
sr = inspectOpNode(secondExpr);
193-
194-
return (fr && sr);
192+
return 0;
195193
}
196194

197195

@@ -205,7 +203,9 @@ inspectOpNode(Expr *expr)
205203
Expr *firstExpr, *secondExpr;
206204

207205
if (nodeTag(expr) != T_Expr || expr->opType != OP_EXPR)
208-
return 0;
206+
return FALSE;
207+
208+
TotalExpr++;
209209

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

0 commit comments

Comments
 (0)