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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * btutils.c
  4.  *   Utility code for Postgres btree implementation.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.27.2.1 1999/08/02 05:24:42 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include "postgres.h"
  15. #include "access/genam.h"
  16. #include "access/istrat.h"
  17. #include "access/nbtree.h"
  18. #include "executor/execdebug.h"
  19. extern int NIndexTupleProcessed;
  20. ScanKey
  21. _bt_mkscankey(Relation rel, IndexTuple itup)
  22. {
  23. ScanKey skey;
  24. TupleDesc itupdesc;
  25. int natts;
  26. int i;
  27. Datum arg;
  28. RegProcedure proc;
  29. bool null;
  30. bits16 flag;
  31. natts = rel->rd_rel->relnatts;
  32. itupdesc = RelationGetDescr(rel);
  33. skey = (ScanKey) palloc(natts * sizeof(ScanKeyData));
  34. for (i = 0; i < natts; i++)
  35. {
  36. arg = index_getattr(itup, i + 1, itupdesc, &null);
  37. if (null)
  38. {
  39. proc = F_NULLVALUE;
  40. flag = SK_ISNULL;
  41. }
  42. else
  43. {
  44. proc = index_getprocid(rel, i + 1, BTORDER_PROC);
  45. flag = 0x0;
  46. }
  47. ScanKeyEntryInitialize(&skey[i], flag, (AttrNumber) (i + 1), proc, arg);
  48. }
  49. return skey;
  50. }
  51. void
  52. _bt_freeskey(ScanKey skey)
  53. {
  54. pfree(skey);
  55. }
  56. void
  57. _bt_freestack(BTStack stack)
  58. {
  59. BTStack ostack;
  60. while (stack != (BTStack) NULL)
  61. {
  62. ostack = stack;
  63. stack = stack->bts_parent;
  64. pfree(ostack->bts_btitem);
  65. pfree(ostack);
  66. }
  67. }
  68. /*
  69.  * _bt_orderkeys() -- Put keys in a sensible order for conjunctive quals.
  70.  *
  71.  * The order of the keys in the qual match the ordering imposed by
  72.  * the index. This routine only needs to be called if there are
  73.  * more than one qual clauses using this index.
  74.  */
  75. void
  76. _bt_orderkeys(Relation relation, BTScanOpaque so)
  77. {
  78. ScanKey xform;
  79. ScanKeyData *cur;
  80. StrategyMap map;
  81. int nbytes;
  82. long test;
  83. int i,
  84. j;
  85. int init[BTMaxStrategyNumber + 1];
  86. ScanKey key;
  87. uint16 numberOfKeys = so->numberOfKeys;
  88. uint16 new_numberOfKeys = 0;
  89. AttrNumber attno = 1;
  90. if (numberOfKeys < 1)
  91. return;
  92. key = so->keyData;
  93. cur = &key[0];
  94. if (cur->sk_attno != 1)
  95. elog(ERROR, "_bt_orderkeys: key(s) for attribute 1 missed");
  96. if (numberOfKeys == 1)
  97. {
  98. /*
  99.  * We don't use indices for 'A is null' and 'A is not null'
  100.  * currently and 'A < = > <> NULL' is non-sense' - so qual is not
  101.  * Ok. - vadim 03/21/97
  102.  */
  103. if (cur->sk_flags & SK_ISNULL)
  104. so->qual_ok = 0;
  105. so->numberOfFirstKeys = 1;
  106. return;
  107. }
  108. /* get space for the modified array of keys */
  109. nbytes = BTMaxStrategyNumber * sizeof(ScanKeyData);
  110. xform = (ScanKey) palloc(nbytes);
  111. MemSet(xform, 0, nbytes);
  112. map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
  113.   BTMaxStrategyNumber,
  114.   attno);
  115. for (j = 0; j <= BTMaxStrategyNumber; j++)
  116. init[j] = 0;
  117. /* check each key passed in */
  118. for (i = 0;;)
  119. {
  120. if (i < numberOfKeys)
  121. cur = &key[i];
  122. if (cur->sk_flags & SK_ISNULL) /* see comments above */
  123. so->qual_ok = 0;
  124. if (i == numberOfKeys || cur->sk_attno != attno)
  125. {
  126. if (cur->sk_attno != attno + 1 && i < numberOfKeys)
  127. elog(ERROR, "_bt_orderkeys: key(s) for attribute %d missed", attno + 1);
  128. /*
  129.  * If = has been specified, no other key will be used. In case
  130.  * of key < 2 && key == 1 and so on we have to set qual_ok to
  131.  * 0
  132.  */
  133. if (init[BTEqualStrategyNumber - 1])
  134. {
  135. ScanKeyData *eq,
  136.    *chk;
  137. eq = &xform[BTEqualStrategyNumber - 1];
  138. for (j = BTMaxStrategyNumber; --j >= 0;)
  139. {
  140. if (j == (BTEqualStrategyNumber - 1) || init[j] == 0)
  141. continue;
  142. chk = &xform[j];
  143. test = (long) fmgr(chk->sk_procedure, eq->sk_argument, chk->sk_argument);
  144. if (!test)
  145. so->qual_ok = 0;
  146. }
  147. init[BTLessStrategyNumber - 1] = 0;
  148. init[BTLessEqualStrategyNumber - 1] = 0;
  149. init[BTGreaterEqualStrategyNumber - 1] = 0;
  150. init[BTGreaterStrategyNumber - 1] = 0;
  151. }
  152. /* only one of <, <= */
  153. if (init[BTLessStrategyNumber - 1]
  154. && init[BTLessEqualStrategyNumber - 1])
  155. {
  156. ScanKeyData *lt,
  157.    *le;
  158. lt = &xform[BTLessStrategyNumber - 1];
  159. le = &xform[BTLessEqualStrategyNumber - 1];
  160. /*
  161.  * DO NOT use the cached function stuff here -- this is
  162.  * key ordering, happens only when the user expresses a
  163.  * hokey qualification, and gets executed only once,
  164.  * anyway. The transform maps are hard-coded, and can't
  165.  * be initialized in the correct way.
  166.  */
  167. test = (long) fmgr(le->sk_procedure, lt->sk_argument, le->sk_argument);
  168. if (test)
  169. init[BTLessEqualStrategyNumber - 1] = 0;
  170. else
  171. init[BTLessStrategyNumber - 1] = 0;
  172. }
  173. /* only one of >, >= */
  174. if (init[BTGreaterStrategyNumber - 1]
  175. && init[BTGreaterEqualStrategyNumber - 1])
  176. {
  177. ScanKeyData *gt,
  178.    *ge;
  179. gt = &xform[BTGreaterStrategyNumber - 1];
  180. ge = &xform[BTGreaterEqualStrategyNumber - 1];
  181. /* see note above on function cache */
  182. test = (long) fmgr(ge->sk_procedure, gt->sk_argument, ge->sk_argument);
  183. if (test)
  184. init[BTGreaterEqualStrategyNumber - 1] = 0;
  185. else
  186. init[BTGreaterStrategyNumber - 1] = 0;
  187. }
  188. /* okay, reorder and count */
  189. for (j = BTMaxStrategyNumber; --j >= 0;)
  190. if (init[j])
  191. key[new_numberOfKeys++] = xform[j];
  192. if (attno == 1)
  193. so->numberOfFirstKeys = new_numberOfKeys;
  194. if (i == numberOfKeys)
  195. break;
  196. /* initialization for new attno */
  197. attno = cur->sk_attno;
  198. MemSet(xform, 0, nbytes);
  199. map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
  200.   BTMaxStrategyNumber,
  201.   attno);
  202. /* haven't looked at any strategies yet */
  203. for (j = 0; j <= BTMaxStrategyNumber; j++)
  204. init[j] = 0;
  205. }
  206. for (j = BTMaxStrategyNumber; --j >= 0;)
  207. {
  208. if (cur->sk_procedure == map->entry[j].sk_procedure)
  209. break;
  210. }
  211. /* have we seen one of these before? */
  212. if (init[j])
  213. {
  214. /* yup, use the appropriate value */
  215. test = (long) FMGR_PTR2(&cur->sk_func, cur->sk_argument, xform[j].sk_argument);
  216. if (test)
  217. xform[j].sk_argument = cur->sk_argument;
  218. else if (j == (BTEqualStrategyNumber - 1))
  219. so->qual_ok = 0;/* key == a && key == b, but a != b */
  220. }
  221. else
  222. {
  223. /* nope, use this value */
  224. memmove(&xform[j], cur, sizeof(*cur));
  225. init[j] = 1;
  226. }
  227. i++;
  228. }
  229. so->numberOfKeys = new_numberOfKeys;
  230. pfree(xform);
  231. }
  232. BTItem
  233. _bt_formitem(IndexTuple itup)
  234. {
  235. int nbytes_btitem;
  236. BTItem btitem;
  237. Size tuplen;
  238. extern Oid newoid();
  239. /*
  240.  * see comments in btbuild
  241.  *
  242.  * if (itup->t_info & INDEX_NULL_MASK) elog(ERROR, "btree indices cannot
  243.  * include null keys");
  244.  */
  245. /* make a copy of the index tuple with room for the sequence number */
  246. tuplen = IndexTupleSize(itup);
  247. nbytes_btitem = tuplen + (sizeof(BTItemData) - sizeof(IndexTupleData));
  248. btitem = (BTItem) palloc(nbytes_btitem);
  249. memmove((char *) &(btitem->bti_itup), (char *) itup, tuplen);
  250. return btitem;
  251. }
  252. #ifdef NOT_USED
  253. bool
  254. _bt_checkqual(IndexScanDesc scan, IndexTuple itup)
  255. {
  256. BTScanOpaque so;
  257. so = (BTScanOpaque) scan->opaque;
  258. if (so->numberOfKeys > 0)
  259. return (index_keytest(itup, RelationGetDescr(scan->relation),
  260.   so->numberOfKeys, so->keyData));
  261. else
  262. return true;
  263. }
  264. #endif
  265. #ifdef NOT_USED
  266. bool
  267. _bt_checkforkeys(IndexScanDesc scan, IndexTuple itup, Size keysz)
  268. {
  269. BTScanOpaque so;
  270. so = (BTScanOpaque) scan->opaque;
  271. if (keysz > 0 && so->numberOfKeys >= keysz)
  272. return (index_keytest(itup, RelationGetDescr(scan->relation),
  273.   keysz, so->keyData));
  274. else
  275. return true;
  276. }
  277. #endif
  278. bool
  279. _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, Size *keysok)
  280. {
  281. BTScanOpaque so = (BTScanOpaque) scan->opaque;
  282. Size keysz = so->numberOfKeys;
  283. TupleDesc tupdesc;
  284. ScanKey key;
  285. Datum datum;
  286. bool isNull;
  287. int test;
  288. *keysok = 0;
  289. if (keysz == 0)
  290. return true;
  291. key = so->keyData;
  292. tupdesc = RelationGetDescr(scan->relation);
  293. IncrIndexProcessed();
  294. while (keysz > 0)
  295. {
  296. datum = index_getattr(tuple,
  297.   key[0].sk_attno,
  298.   tupdesc,
  299.   &isNull);
  300. /* btree doesn't support 'A is null' clauses, yet */
  301. if (key[0].sk_flags & SK_ISNULL)
  302. return false;
  303. if (isNull)
  304. {
  305. if (*keysok < so->numberOfFirstKeys)
  306. *keysok = -1;
  307. return false;
  308. }
  309. if (key[0].sk_flags & SK_COMMUTE)
  310. {
  311. test = (int) (*fmgr_faddr(&key[0].sk_func))
  312. (DatumGetPointer(key[0].sk_argument),
  313.  datum);
  314. }
  315. else
  316. {
  317. test = (int) (*fmgr_faddr(&key[0].sk_func))
  318. (datum,
  319.  DatumGetPointer(key[0].sk_argument));
  320. }
  321. if (!test == !(key[0].sk_flags & SK_NEGATE))
  322. return false;
  323. keysz -= 1;
  324. key++;
  325. (*keysok)++;
  326. }
  327. return true;
  328. }