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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * rtstrat.c
  4.  *   strategy map data for rtrees.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/access/rtree/rtstrat.c,v 1.11.2.1 1999/08/02 05:24:44 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include "postgres.h"
  15. #include "access/istrat.h"
  16. #include "access/rtree.h"
  17. static StrategyNumber RelationGetRTStrategy(Relation r,
  18.   AttrNumber attnum, RegProcedure proc);
  19. /*
  20.  * Note:  negate, commute, and negatecommute all assume that operators are
  21.  *    ordered as follows in the strategy map:
  22.  *
  23.  * left, left-or-overlap, overlap, right-or-overlap, right, same,
  24.  * contains, contained-by
  25.  *
  26.  * The negate, commute, and negatecommute arrays are used by the planner
  27.  * to plan indexed scans over data that appears in the qualificiation in
  28.  * a boolean negation, or whose operands appear in the wrong order.  For
  29.  * example, if the operator "<%" means "contains", and the user says
  30.  *
  31.  * where not rel.box <% "(10,10,20,20)"::box
  32.  *
  33.  * the planner can plan an index scan by noting that rtree indices have
  34.  * an operator in their operator class for negating <%.
  35.  *
  36.  * Similarly, if the user says something like
  37.  *
  38.  * where "(10,10,20,20)"::box <% rel.box
  39.  *
  40.  * the planner can see that the rtree index on rel.box has an operator in
  41.  * its opclass for commuting <%, and plan the scan using that operator.
  42.  * This added complexity in the access methods makes the planner a lot easier
  43.  * to write.
  44.  */
  45. /* if a op b, what operator tells us if (not a op b)? */
  46. static StrategyNumber RTNegate[RTNStrategies] = {
  47. InvalidStrategy,
  48. InvalidStrategy,
  49. InvalidStrategy,
  50. InvalidStrategy,
  51. InvalidStrategy,
  52. InvalidStrategy,
  53. InvalidStrategy,
  54. InvalidStrategy
  55. };
  56. /* if a op_1 b, what is the operator op_2 such that b op_2 a? */
  57. static StrategyNumber RTCommute[RTNStrategies] = {
  58. InvalidStrategy,
  59. InvalidStrategy,
  60. InvalidStrategy,
  61. InvalidStrategy,
  62. InvalidStrategy,
  63. InvalidStrategy,
  64. InvalidStrategy,
  65. InvalidStrategy
  66. };
  67. /* if a op_1 b, what is the operator op_2 such that (b !op_2 a)? */
  68. static StrategyNumber RTNegateCommute[RTNStrategies] = {
  69. InvalidStrategy,
  70. InvalidStrategy,
  71. InvalidStrategy,
  72. InvalidStrategy,
  73. InvalidStrategy,
  74. InvalidStrategy,
  75. InvalidStrategy,
  76. InvalidStrategy
  77. };
  78. /*
  79.  * Now do the TermData arrays.  These exist in case the user doesn't give
  80.  * us a full set of operators for a particular operator class.  The idea
  81.  * is that by making multiple comparisons using any one of the supplied
  82.  * operators, we can decide whether two n-dimensional polygons are equal.
  83.  * For example, if a contains b and b contains a, we may conclude that
  84.  * a and b are equal.
  85.  *
  86.  * The presence of the TermData arrays in all this is a historical accident.
  87.  * Early in the development of the POSTGRES access methods, it was believed
  88.  * that writing functions was harder than writing arrays. This is wrong;
  89.  * TermData is hard to understand and hard to get right.  In general, when
  90.  * someone populates a new operator class, the populate it completely.  If
  91.  * Mike Hirohama had forced Cimarron Taylor to populate the strategy map
  92.  * for btree int2_ops completely in 1988, you wouldn't have to deal with
  93.  * all this now.  Too bad for you.
  94.  *
  95.  * Since you can't necessarily do this in all cases (for example, you can't
  96.  * do it given only "intersects" or "disjoint"), TermData arrays for some
  97.  * operators don't appear below.
  98.  *
  99.  * Note that if you DO supply all the operators required in a given opclass
  100.  * by inserting them into the pg_opclass system catalog, you can get away
  101.  * without doing all this TermData stuff. Since the rtree code is intended
  102.  * to be a reference for access method implementors, I'm doing TermData
  103.  * correctly here.
  104.  *
  105.  * Note on style: these are all actually of type StrategyTermData, but
  106.  * since those have variable-length data at the end of the struct we can't
  107.  * properly initialize them if we declare them to be what they are.
  108.  */
  109. /* if you only have "contained-by", how do you determine equality? */
  110. static uint16 RTContainedByTermData[] = {
  111. 2, /* make two comparisons */
  112. RTContainedByStrategyNumber,/* use "a contained-by b" */
  113. 0x0, /* without any magic */
  114. RTContainedByStrategyNumber,/* then use contained-by, */
  115. SK_COMMUTE /* swapping a and b */
  116. };
  117. /* if you only have "contains", how do you determine equality? */
  118. static uint16 RTContainsTermData[] = {
  119. 2, /* make two comparisons */
  120. RTContainsStrategyNumber, /* use "a contains b" */
  121. 0x0, /* without any magic */
  122. RTContainsStrategyNumber, /* then use contains again, */
  123. SK_COMMUTE /* swapping a and b */
  124. };
  125. /* now put all that together in one place for the planner */
  126. static StrategyTerm RTEqualExpressionData[] = {
  127. (StrategyTerm) RTContainedByTermData,
  128. (StrategyTerm) RTContainsTermData,
  129. NULL
  130. };
  131. /*
  132.  * If you were sufficiently attentive to detail, you would go through
  133.  * the ExpressionData pain above for every one of the seven strategies
  134.  * we defined.  I am not. Now we declare the StrategyEvaluationData
  135.  * structure that gets shipped around to help the planner and the access
  136.  * method decide what sort of scan it should do, based on (a) what the
  137.  * user asked for, (b) what operators are defined for a particular opclass,
  138.  * and (c) the reams of information we supplied above.
  139.  *
  140.  * The idea of all of this initialized data is to make life easier on the
  141.  * user when he defines a new operator class to use this access method.
  142.  * By filling in all the data, we let him get away with leaving holes in his
  143.  * operator class, and still let him use the index.  The added complexity
  144.  * in the access methods just isn't worth the trouble, though.
  145.  */
  146. static StrategyEvaluationData RTEvaluationData = {
  147. RTNStrategies, /* # of strategies */
  148. (StrategyTransformMap) RTNegate, /* how to do (not qual) */
  149. (StrategyTransformMap) RTCommute, /* how to swap operands */
  150. (StrategyTransformMap) RTNegateCommute, /* how to do both */
  151. {
  152. NULL, /* express left */
  153. NULL, /* express overleft */
  154. NULL, /* express over */
  155. NULL, /* express overright */
  156. NULL, /* express right */
  157. (StrategyExpression) RTEqualExpressionData, /* express same */
  158. NULL, /* express contains */
  159. NULL, /* express contained-by */
  160. NULL,
  161. NULL,
  162. NULL
  163. }
  164. };
  165. /*
  166.  * Okay, now something peculiar to rtrees that doesn't apply to most other
  167.  * indexing structures:  When we're searching a tree for a given value, we
  168.  * can't do the same sorts of comparisons on internal node entries as we
  169.  * do at leaves.  The reason is that if we're looking for (say) all boxes
  170.  * that are the same as (0,0,10,10), then we need to find all leaf pages
  171.  * that overlap that region.  So internally we search for overlap, and at
  172.  * the leaf we search for equality.
  173.  *
  174.  * This array maps leaf search operators to the internal search operators.
  175.  * We assume the normal ordering on operators:
  176.  *
  177.  * left, left-or-overlap, overlap, right-or-overlap, right, same,
  178.  * contains, contained-by
  179.  */
  180. static StrategyNumber RTOperMap[RTNStrategies] = {
  181. RTOverLeftStrategyNumber,
  182. RTOverLeftStrategyNumber,
  183. RTOverlapStrategyNumber,
  184. RTOverRightStrategyNumber,
  185. RTOverRightStrategyNumber,
  186. RTContainsStrategyNumber,
  187. RTContainsStrategyNumber,
  188. RTOverlapStrategyNumber
  189. };
  190. static StrategyNumber
  191. RelationGetRTStrategy(Relation r,
  192.   AttrNumber attnum,
  193.   RegProcedure proc)
  194. {
  195. return RelationGetStrategy(r, attnum, &RTEvaluationData, proc);
  196. }
  197. #ifdef NOT_USED
  198. bool
  199. RelationInvokeRTStrategy(Relation r,
  200.  AttrNumber attnum,
  201.  StrategyNumber s,
  202.  Datum left,
  203.  Datum right)
  204. {
  205. return (RelationInvokeStrategy(r, &RTEvaluationData, attnum, s,
  206.    left, right));
  207. }
  208. #endif
  209. RegProcedure
  210. RTMapOperator(Relation r,
  211.   AttrNumber attnum,
  212.   RegProcedure proc)
  213. {
  214. StrategyNumber procstrat;
  215. StrategyMap strategyMap;
  216. procstrat = RelationGetRTStrategy(r, attnum, proc);
  217. strategyMap = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(r),
  218.   RTNStrategies,
  219.   attnum);
  220. return strategyMap->entry[RTOperMap[procstrat - 1] - 1].sk_procedure;
  221. }