prepkeyset.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:6k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * prepkeyset.c
  4.  *   Special preperation for keyset queries.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *-------------------------------------------------------------------------
  9.  */
  10. #include "postgres.h"
  11. #include "optimizer/planmain.h"
  12. /*
  13.  * Node_Copy
  14.  *   a macro to simplify calling of copyObject on the specified field
  15.  */
  16. #define Node_Copy(from, newnode, field) newnode->field = copyObject(from->field)
  17. bool _use_keyset_query_optimizer = FALSE;
  18. static int inspectOpNode(Expr *expr);
  19. static int inspectAndNode(Expr *expr);
  20. static int inspectOrNode(Expr *expr);
  21. static int TotalExpr;
  22. /**********************************************************************
  23.  *  This routine transforms query trees with the following form:
  24.  *  SELECT a,b, ... FROM one_table WHERE
  25.  *   (v1 = const1 AND v2 = const2 [ vn = constn ]) OR
  26.  *   (v1 = const3 AND v2 = const4 [ vn = constn ]) OR
  27.  *   (v1 = const5 AND v2 = const6 [ vn = constn ]) OR
  28.  *    ...
  29.  *   [(v1 = constn AND v2 = constn [ vn = constn ])]
  30.  *
  31.  *    into
  32.  *
  33.  *  SELECT a,b, ... FROM one_table WHERE
  34.  *   (v1 = const1 AND v2 = const2 [ vn = constn ]) UNION
  35.  *  SELECT a,b, ... FROM one_table WHERE
  36.  *   (v1 = const3 AND v2 = const4 [ vn = constn ]) UNION
  37.  *  SELECT a,b, ... FROM one_table WHERE
  38.  *   (v1 = const5 AND v2 = const6 [ vn = constn ]) UNION
  39.  *    ...
  40.  *  SELECT a,b, ... FROM one_table WHERE
  41.  *   [(v1 = constn AND v2 = constn [ vn = constn ])]
  42.  *
  43.  *
  44.  *  To qualify for transformation the query must not be a sub select,
  45.  *  a HAVING, or a GROUP BY. It must be a single table and have KSQO
  46.  *  set to 'on'.
  47.  *
  48.  *  The primary use of this transformation is to avoid the exponrntial
  49.  *  memory consumption of cnfify() and to make use of index access
  50.  *  methods.
  51.  *
  52.  *   daveh@insightdist.com   1998-08-31
  53.  *
  54.  *  May want to also prune out duplicate terms.
  55.  **********************************************************************/
  56. void
  57. transformKeySetQuery(Query *origNode)
  58. {
  59. /* Qualify as a key set query candidate  */
  60. if (_use_keyset_query_optimizer == FALSE ||
  61. origNode->groupClause ||
  62. origNode->havingQual ||
  63. origNode->hasAggs ||
  64. origNode->utilityStmt ||
  65. origNode->unionClause ||
  66. origNode->unionall ||
  67. origNode->hasSubLinks ||
  68. origNode->commandType != CMD_SELECT)
  69. return;
  70. /* Qualify single table query */
  71. if (length(origNode->rtable) != 1)
  72. return;
  73. /* Sorry about the global, not worth passing around */
  74. /* 9 expressions seems like a good number. More than 9 */
  75. /* and it starts to slow down quite a bit */
  76. TotalExpr = 0;
  77. /*************************/
  78. /* Qualify where clause */
  79. /*************************/
  80. if (!inspectOrNode((Expr *) origNode->qual) || TotalExpr < 9)
  81. return;
  82. /* Copy essential elements into a union node */
  83. while (((Expr *) origNode->qual)->opType == OR_EXPR)
  84. {
  85. Query    *unionNode = makeNode(Query);
  86. /* Pull up Expr =  */
  87. unionNode->qual = lsecond(((Expr *) origNode->qual)->args);
  88. /* Pull up balance of tree */
  89. origNode->qual = lfirst(((Expr *) origNode->qual)->args);
  90. unionNode->commandType = origNode->commandType;
  91. unionNode->resultRelation = origNode->resultRelation;
  92. unionNode->isPortal = origNode->isPortal;
  93. unionNode->isBinary = origNode->isBinary;
  94. if (origNode->uniqueFlag)
  95. unionNode->uniqueFlag = pstrdup(origNode->uniqueFlag);
  96. Node_Copy(origNode, unionNode, sortClause);
  97. Node_Copy(origNode, unionNode, rtable);
  98. Node_Copy(origNode, unionNode, targetList);
  99. origNode->unionClause = lappend(origNode->unionClause, unionNode);
  100. }
  101. return;
  102. }
  103. static int
  104. /**********************************************************************
  105.  *  Checks for 1 or more OR terms w/ 1 or more AND terms.
  106.  *  AND terms must be equal in size.
  107.  *  Returns the number of each AND term.
  108.  **********************************************************************/
  109. inspectOrNode(Expr *expr)
  110. {
  111. int rc;
  112. Expr    *firstExpr,
  113.    *secondExpr;
  114. if (!(expr && nodeTag(expr) == T_Expr && expr->opType == OR_EXPR))
  115. return 0;
  116. firstExpr = lfirst(expr->args);
  117. secondExpr = lsecond(expr->args);
  118. if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
  119. return 0;
  120. if (firstExpr->opType == OR_EXPR && secondExpr->opType == AND_EXPR)
  121. {
  122. if ((rc = inspectOrNode(firstExpr)) == 0)
  123. return 0;
  124. return (rc == inspectAndNode(secondExpr)) ? rc : 0;
  125. }
  126. else if (firstExpr->opType == AND_EXPR && secondExpr->opType == AND_EXPR)
  127. {
  128. if ((rc = inspectAndNode(firstExpr)) == 0)
  129. return 0;
  130. return (rc == inspectAndNode(secondExpr)) ? rc : 0;
  131. }
  132. return 0;
  133. }
  134. static int
  135. /**********************************************************************
  136.  * Check for one or more AND terms.   Each sub-term must be a T_Const
  137.  * T_Var expression.
  138.  * Returns the number of AND terms.
  139.  **********************************************************************/
  140. inspectAndNode(Expr *expr)
  141. {
  142. int rc;
  143. Expr    *firstExpr,
  144.    *secondExpr;
  145. if (!(expr && nodeTag(expr) == T_Expr && expr->opType == AND_EXPR))
  146. return 0;
  147. firstExpr = lfirst(expr->args);
  148. secondExpr = lsecond(expr->args);
  149. if (nodeTag(firstExpr) != T_Expr || nodeTag(secondExpr) != T_Expr)
  150. return 0;
  151. if (firstExpr->opType == AND_EXPR &&
  152. secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
  153. {
  154. rc = inspectAndNode(firstExpr);
  155. return ((rc) ? (rc + 1) : 0); /* Add up the AND nodes */
  156. }
  157. else if (firstExpr->opType == OP_EXPR && inspectOpNode(firstExpr) &&
  158.  secondExpr->opType == OP_EXPR && inspectOpNode(secondExpr))
  159. return 1;
  160. return 0;
  161. }
  162. static int
  163. /******************************************************************
  164.  * Return TRUE if T_Var = T_Const, else FALSE
  165.  * Actually it does not test for =. Need to do this!
  166.  ******************************************************************/
  167. inspectOpNode(Expr *expr)
  168. {
  169. Expr    *firstExpr,
  170.    *secondExpr;
  171. if (nodeTag(expr) != T_Expr || expr->opType != OP_EXPR)
  172. return FALSE;
  173. TotalExpr++;
  174. firstExpr = lfirst(expr->args);
  175. secondExpr = lsecond(expr->args);
  176. return (firstExpr && secondExpr && nodeTag(firstExpr) == T_Var && nodeTag(secondExpr) == T_Const);
  177. }