OSDN Git Service

Oops missing file.
authorBruce Momjian <bruce@momjian.us>
Thu, 3 Sep 1998 05:09:27 +0000 (05:09 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 3 Sep 1998 05:09:27 +0000 (05:09 +0000)
src/backend/optimizer/prep/prepkeyset.c [new file with mode: 0644]

diff --git a/src/backend/optimizer/prep/prepkeyset.c b/src/backend/optimizer/prep/prepkeyset.c
new file mode 100644 (file)
index 0000000..a8301a8
--- /dev/null
@@ -0,0 +1,213 @@
+/*-------------------------------------------------------------------------
+ *
+ * prepkeyset.c--
+ *       Special preperation for keyset queries.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#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:
+ *       SELECT a,b, ... FROM one_table WHERE
+ *        (v1 = const1 AND v2 = const2 [ vn = constn ]) OR
+ *        (v1 = const3 AND v2 = const4 [ vn = constn ]) OR
+ *        (v1 = const5 AND v2 = const6 [ vn = constn ]) OR
+ *                         ...
+ *        [(v1 = constn AND v2 = constn [ vn = constn ])]
+ *
+ *                             into 
+ *
+ *       SELECT a,b, ... FROM one_table WHERE
+ *        (v1 = const1 AND v2 = const2 [ vn = constn ]) UNION
+ *       SELECT a,b, ... FROM one_table WHERE
+ *        (v1 = const3 AND v2 = const4 [ vn = constn ]) UNION
+ *       SELECT a,b, ... FROM one_table WHERE
+ *        (v1 = const5 AND v2 = const6 [ vn = constn ]) UNION
+ *                         ...
+ *       SELECT a,b, ... FROM one_table WHERE
+ *        [(v1 = constn AND v2 = constn [ vn = constn ])]
+ *
+ *
+ *   To qualify for transformation the query must not be a sub select,
+ *   a HAVING, or a GROUP BY.   It must be a single table and have KSQO
+ *   set to 'on'.  
+ *
+ *   The primary use of this transformation is to avoid the exponrntial 
+ *   memory consumption of cnfify() and to make use of index access
+ *   methods.
+ *
+ *        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)
+{
+       /*   Qualify as a key set query candidate  */
+       if (_use_keyset_query_optimizer == FALSE || 
+                       origNode->groupClause ||
+                       origNode->havingQual ||
+                       origNode->hasAggs ||
+                       origNode->utilityStmt ||
+                       origNode->unionClause ||
+                       origNode->unionall ||
+                       origNode->hasSubLinks ||
+                       origNode->commandType != CMD_SELECT)
+               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);
+
+               /*   Pull up Expr =  */
+               unionNode->qual = lsecond(((Expr*)origNode->qual)->args);
+
+               /*   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;
+               unionNode->isBinary = origNode->isBinary;
+
+               if (origNode->uniqueFlag)
+                       unionNode->uniqueFlag = pstrdup(origNode->uniqueFlag);
+
+               Node_Copy(origNode, unionNode, sortClause);
+               Node_Copy(origNode, unionNode, rtable);
+               Node_Copy(origNode, unionNode, targetList);
+
+               origNode->unionClause = lappend(origNode->unionClause, unionNode);
+       }
+       return;
+}
+
+
+
+
+static int
+inspectOrNode(Expr *expr)
+{
+       int fr = 0, sr = 0;
+       Expr *firstExpr, *secondExpr;
+
+       if ( ! (expr && nodeTag(expr) == T_Expr && expr->opType == OR_EXPR))
+               return 0;
+
+       firstExpr = lfirst(expr->args);
+       secondExpr = lsecond(expr->args);
+       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))
+               return 0;
+
+       firstExpr = lfirst(expr->args);
+       secondExpr = lsecond(expr->args);
+       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);              
+}
+
+
+static int
+/******************************************************************
+ *  Return TRUE if T_Var = T_Const, else FALSE
+ *  Actually it does not test for =.    Need to do this!
+ ******************************************************************/
+inspectOpNode(Expr *expr)
+{
+       Expr *firstExpr, *secondExpr;
+
+       if (nodeTag(expr) != T_Expr || expr->opType != OP_EXPR)
+               return 0;
+
+       firstExpr = lfirst(expr->args);
+       secondExpr = lsecond(expr->args);
+       return  (firstExpr && secondExpr && nodeTag(firstExpr) == T_Var && nodeTag(secondExpr) == T_Const);
+}