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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * lselect.c
  4.  *   leftist tree selection algorithm (linked priority queue--Knuth, Vol.3,
  5.  *   pp.150-52)
  6.  *
  7.  * Copyright (c) 1994, Regents of the University of California
  8.  *
  9.  *
  10.  * IDENTIFICATION
  11.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/utils/sort/lselect.c,v 1.16.2.1 1999/08/02 05:25:17 scrappy Exp $
  12.  *
  13.  *-------------------------------------------------------------------------
  14.  */
  15. #include "postgres.h"
  16. #include "access/heapam.h"
  17. #include "utils/lselect.h"
  18. /*
  19.  * lmerge - merges two leftist trees into one
  20.  *
  21.  * Note:
  22.  * Enforcing the rule that pt->lt_dist >= qt->lt_dist may
  23.  * simplifify much of the code.  Removing recursion will not
  24.  * speed up code significantly.
  25.  */
  26. struct leftist *
  27. lmerge(struct leftist * pt, struct leftist * qt, LeftistContext context)
  28. {
  29. struct leftist *root,
  30.    *majorLeftist,
  31.    *minorLeftist;
  32. int dist;
  33. if (tuplecmp(pt->lt_tuple, qt->lt_tuple, context))
  34. {
  35. root = pt;
  36. majorLeftist = qt;
  37. }
  38. else
  39. {
  40. root = qt;
  41. majorLeftist = pt;
  42. }
  43. if (root->lt_left == NULL)
  44. root->lt_left = majorLeftist;
  45. else
  46. {
  47. if ((minorLeftist = root->lt_right) != NULL)
  48. majorLeftist = lmerge(majorLeftist, minorLeftist, context);
  49. if ((dist = root->lt_left->lt_dist) < majorLeftist->lt_dist)
  50. {
  51. root->lt_dist = 1 + dist;
  52. root->lt_right = root->lt_left;
  53. root->lt_left = majorLeftist;
  54. }
  55. else
  56. {
  57. root->lt_dist = 1 + majorLeftist->lt_dist;
  58. root->lt_right = majorLeftist;
  59. }
  60. }
  61. return root;
  62. }
  63. static struct leftist *
  64. linsert(struct leftist * root, struct leftist * new1, LeftistContext context)
  65. {
  66. struct leftist *left,
  67.    *right;
  68. if (!tuplecmp(root->lt_tuple, new1->lt_tuple, context))
  69. {
  70. new1->lt_left = root;
  71. return new1;
  72. }
  73. left = root->lt_left;
  74. right = root->lt_right;
  75. if (right == NULL)
  76. {
  77. if (left == NULL)
  78. root->lt_left = new1;
  79. else
  80. {
  81. root->lt_right = new1;
  82. root->lt_dist = 2;
  83. }
  84. return root;
  85. }
  86. right = linsert(right, new1, context);
  87. if (right->lt_dist < left->lt_dist)
  88. {
  89. root->lt_dist = 1 + left->lt_dist;
  90. root->lt_left = right;
  91. root->lt_right = left;
  92. }
  93. else
  94. {
  95. root->lt_dist = 1 + right->lt_dist;
  96. root->lt_right = right;
  97. }
  98. return root;
  99. }
  100. /*
  101.  * gettuple - returns tuple at top of tree (Tuples)
  102.  *
  103.  * Returns:
  104.  * tuple at top of tree, NULL if failed ALLOC()
  105.  * *devnum is set to the devnum of tuple returned
  106.  * *treep is set to the new tree
  107.  *
  108.  * Note:
  109.  * *treep must not be NULL
  110.  * NULL is currently never returned BUG
  111.  */
  112. HeapTuple
  113. gettuple(struct leftist ** treep,
  114.  short *devnum, /* device from which tuple came */
  115.  LeftistContext context)
  116. {
  117. struct leftist *tp;
  118. HeapTuple tup;
  119. tp = *treep;
  120. tup = tp->lt_tuple;
  121. *devnum = tp->lt_devnum;
  122. if (tp->lt_dist == 1) /* lt_left == NULL */
  123. *treep = tp->lt_left;
  124. else
  125. *treep = lmerge(tp->lt_left, tp->lt_right, context);
  126. pfree(tp);
  127. return tup;
  128. }
  129. /*
  130.  * puttuple - inserts new tuple into tree
  131.  *
  132.  * Returns:
  133.  * NULL iff failed ALLOC()
  134.  *
  135.  * Note:
  136.  * Currently never returns NULL BUG
  137.  */
  138. void
  139. puttuple(struct leftist ** treep,
  140.  HeapTuple newtuple,
  141.  short devnum,
  142.  LeftistContext context)
  143. {
  144. struct leftist *new1;
  145. struct leftist *tp;
  146. new1 = (struct leftist *) palloc((unsigned) sizeof(struct leftist));
  147. new1->lt_dist = 1;
  148. new1->lt_devnum = devnum;
  149. new1->lt_tuple = newtuple;
  150. new1->lt_left = NULL;
  151. new1->lt_right = NULL;
  152. if ((tp = *treep) == NULL)
  153. *treep = new1;
  154. else
  155. *treep = linsert(tp, new1, context);
  156. return;
  157. }
  158. /*
  159.  * tuplecmp - Compares two tuples with respect CmpList
  160.  *
  161.  * Returns:
  162.  * 1 if left < right ;0 otherwise
  163.  * Assumtions:
  164.  */
  165. int
  166. tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context)
  167. {
  168. int nkey;
  169. int result = 0;
  170. if (ltup == (HeapTuple) NULL)
  171. return 0;
  172. if (rtup == (HeapTuple) NULL)
  173. return 1;
  174. for (nkey = 0; nkey < context->nKeys; nkey++)
  175. {
  176. ScanKey thisKey = & context->scanKeys[nkey];
  177. Datum lattr,
  178. rattr;
  179. bool lisnull,
  180. risnull;
  181. lattr = heap_getattr(ltup, thisKey->sk_attno,
  182.  context->tupDesc, &lisnull);
  183. rattr = heap_getattr(rtup, thisKey->sk_attno,
  184.  context->tupDesc, &risnull);
  185. if (lisnull)
  186. {
  187. if (risnull)
  188. continue; /* treat two nulls as equal */
  189. return 0; /* else, a null sorts after all else */
  190. }
  191. if (risnull)
  192. return 1;
  193. if (thisKey->sk_flags & SK_COMMUTE)
  194. {
  195. if (!(result =
  196.   (long) (*fmgr_faddr(&thisKey->sk_func)) (rattr, lattr)))
  197. result =
  198. -(long) (*fmgr_faddr(&thisKey->sk_func)) (lattr, rattr);
  199. }
  200. else
  201. {
  202. if (!(result =
  203.   (long) (*fmgr_faddr(&thisKey->sk_func)) (lattr, rattr)))
  204. result =
  205. -(long) (*fmgr_faddr(&thisKey->sk_func)) (rattr, lattr);
  206. }
  207. if (result)
  208. break;
  209. }
  210. return result == 1;
  211. }
  212. #ifdef EBUG
  213. void
  214. checktree(struct leftist * tree, LeftistContext context)
  215. {
  216. int lnodes;
  217. int rnodes;
  218. if (tree == NULL)
  219. {
  220. puts("Null tree.");
  221. return;
  222. }
  223. lnodes = checktreer(tree->lt_left, 1, context);
  224. rnodes = checktreer(tree->lt_right, 1, context);
  225. if (lnodes < 0)
  226. {
  227. lnodes = -lnodes;
  228. puts("0:tBad left side.");
  229. }
  230. if (rnodes < 0)
  231. {
  232. rnodes = -rnodes;
  233. puts("0:tBad right side.");
  234. }
  235. if (lnodes == 0)
  236. {
  237. if (rnodes != 0)
  238. puts("0:tLeft and right reversed.");
  239. if (tree->lt_dist != 1)
  240. puts("0:tDistance incorrect.");
  241. }
  242. else if (rnodes == 0)
  243. {
  244. if (tree->lt_dist != 1)
  245. puts("0:tDistance incorrect.");
  246. }
  247. else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist)
  248. {
  249. puts("0:tLeft and right reversed.");
  250. if (tree->lt_dist != 1 + tree->lt_left->lt_dist)
  251. puts("0:tDistance incorrect.");
  252. }
  253. else if (tree->lt_dist != 1 + tree->lt_right->lt_dist)
  254. puts("0:tDistance incorrect.");
  255. if (lnodes > 0)
  256. if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context))
  257. printf("%d:tLeft child < parent.n");
  258. if (rnodes > 0)
  259. if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context))
  260. printf("%d:tRight child < parent.n");
  261. printf("Tree has %d nodesn", 1 + lnodes + rnodes);
  262. }
  263. int
  264. checktreer(struct leftist * tree, int level, LeftistContext context)
  265. {
  266. int lnodes,
  267. rnodes;
  268. int error = 0;
  269. if (tree == NULL)
  270. return 0;
  271. lnodes = checktreer(tree->lt_left, level + 1, context);
  272. rnodes = checktreer(tree->lt_right, level + 1, context);
  273. if (lnodes < 0)
  274. {
  275. error = 1;
  276. lnodes = -lnodes;
  277. printf("%d:tBad left side.n", level);
  278. }
  279. if (rnodes < 0)
  280. {
  281. error = 1;
  282. rnodes = -rnodes;
  283. printf("%d:tBad right side.n", level);
  284. }
  285. if (lnodes == 0)
  286. {
  287. if (rnodes != 0)
  288. {
  289. error = 1;
  290. printf("%d:tLeft and right reversed.n", level);
  291. }
  292. if (tree->lt_dist != 1)
  293. {
  294. error = 1;
  295. printf("%d:tDistance incorrect.n", level);
  296. }
  297. }
  298. else if (rnodes == 0)
  299. {
  300. if (tree->lt_dist != 1)
  301. {
  302. error = 1;
  303. printf("%d:tDistance incorrect.n", level);
  304. }
  305. }
  306. else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist)
  307. {
  308. error = 1;
  309. printf("%d:tLeft and right reversed.n", level);
  310. if (tree->lt_dist != 1 + tree->lt_left->lt_dist)
  311. printf("%d:tDistance incorrect.n", level);
  312. }
  313. else if (tree->lt_dist != 1 + tree->lt_right->lt_dist)
  314. {
  315. error = 1;
  316. printf("%d:tDistance incorrect.n", level);
  317. }
  318. if (lnodes > 0)
  319. if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context))
  320. {
  321. error = 1;
  322. printf("%d:tLeft child < parent.n");
  323. }
  324. if (rnodes > 0)
  325. if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context))
  326. {
  327. error = 1;
  328. printf("%d:tRight child < parent.n");
  329. }
  330. if (error)
  331. return -1 + -lnodes + -rnodes;
  332. return 1 + lnodes + rnodes;
  333. }
  334. #endif