1 /*-------------------------------------------------------------------------
4 * leftist tree selection algorithm (linked priority queue--Knuth, Vol.3,
7 * Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.11 1998/01/31 04:39:12 momjian Exp $
13 *-------------------------------------------------------------------------
20 #include "storage/buf.h"
21 #include "access/skey.h"
22 #include "access/heapam.h"
23 #include "access/htup.h"
24 #include "utils/rel.h"
26 #include "utils/psort.h"
27 #include "utils/lselect.h"
30 * lmerge - merges two leftist trees into one
33 * Enforcing the rule that pt->lt_dist >= qt->lt_dist may
34 * simplifify much of the code. Removing recursion will not
35 * speed up code significantly.
38 lmerge(struct leftist * pt, struct leftist * qt, LeftistContext context)
40 register struct leftist *root,
45 if (tuplecmp(pt->lt_tuple, qt->lt_tuple, context))
55 if (root->lt_left == NULL)
56 root->lt_left = majorLeftist;
59 if ((minorLeftist = root->lt_right) != NULL)
60 majorLeftist = lmerge(majorLeftist, minorLeftist, context);
61 if ((dist = root->lt_left->lt_dist) < majorLeftist->lt_dist)
63 root->lt_dist = 1 + dist;
64 root->lt_right = root->lt_left;
65 root->lt_left = majorLeftist;
69 root->lt_dist = 1 + majorLeftist->lt_dist;
70 root->lt_right = majorLeftist;
76 static struct leftist *
77 linsert(struct leftist * root, struct leftist * new1, LeftistContext context)
79 register struct leftist *left,
82 if (!tuplecmp(root->lt_tuple, new1->lt_tuple, context))
88 right = root->lt_right;
95 root->lt_right = new1;
100 right = linsert(right, new1, context);
101 if (right->lt_dist < left->lt_dist)
103 root->lt_dist = 1 + left->lt_dist;
104 root->lt_left = right;
105 root->lt_right = left;
109 root->lt_dist = 1 + right->lt_dist;
110 root->lt_right = right;
116 * gettuple - returns tuple at top of tree (Tuples)
119 * tuple at top of tree, NULL if failed ALLOC()
120 * *devnum is set to the devnum of tuple returned
121 * *treep is set to the new tree
124 * *treep must not be NULL
125 * NULL is currently never returned BUG
128 gettuple(struct leftist ** treep,
129 short *devnum, /* device from which tuple came */
130 LeftistContext context)
132 register struct leftist *tp;
137 *devnum = tp->lt_devnum;
138 if (tp->lt_dist == 1) /* lt_left == NULL */
139 *treep = tp->lt_left;
141 *treep = lmerge(tp->lt_left, tp->lt_right, context);
148 * puttuple - inserts new tuple into tree
151 * NULL iff failed ALLOC()
154 * Currently never returns NULL BUG
157 puttuple(struct leftist ** treep,
160 LeftistContext context)
162 register struct leftist *new1;
163 register struct leftist *tp;
165 new1 = (struct leftist *) palloc((unsigned) sizeof(struct leftist));
167 new1->lt_devnum = devnum;
168 new1->lt_tuple = newtuple;
169 new1->lt_left = NULL;
170 new1->lt_right = NULL;
171 if ((tp = *treep) == NULL)
174 *treep = linsert(tp, new1, context);
180 * tuplecmp - Compares two tuples with respect CmpList
183 * 1 if left < right ;0 otherwise
187 tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context)
189 register Datum lattr,
195 if (ltup == (HeapTuple) NULL)
197 if (rtup == (HeapTuple) NULL)
199 while (nkey < context->nKeys && !result)
201 lattr = heap_getattr(ltup,
202 context->scanKeys[nkey].sk_attno,
203 context->tupDesc, &isnull);
206 rattr = heap_getattr(rtup,
207 context->scanKeys[nkey].sk_attno,
212 if (context->scanKeys[nkey].sk_flags & SK_COMMUTE)
215 (long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (rattr, lattr)))
217 -(long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (lattr, rattr);
220 (long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (lattr, rattr)))
222 -(long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (rattr, lattr);
225 return (result == 1);
230 checktree(struct leftist * tree, LeftistContext context)
240 lnodes = checktreer(tree->lt_left, 1, context);
241 rnodes = checktreer(tree->lt_right, 1, context);
245 puts("0:\tBad left side.");
250 puts("0:\tBad right side.");
255 puts("0:\tLeft and right reversed.");
256 if (tree->lt_dist != 1)
257 puts("0:\tDistance incorrect.");
259 else if (rnodes == 0)
261 if (tree->lt_dist != 1)
262 puts("0:\tDistance incorrect.");
264 else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist)
266 puts("0:\tLeft and right reversed.");
267 if (tree->lt_dist != 1 + tree->lt_left->lt_dist)
268 puts("0:\tDistance incorrect.");
270 else if (tree->lt_dist != 1 + tree->lt_right->lt_dist)
271 puts("0:\tDistance incorrect.");
273 if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context))
274 printf("%d:\tLeft child < parent.\n");
276 if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context))
277 printf("%d:\tRight child < parent.\n");
278 printf("Tree has %d nodes\n", 1 + lnodes + rnodes);
282 checktreer(struct leftist * tree, int level, LeftistContext context)
290 lnodes = checktreer(tree->lt_left, level + 1, context);
291 rnodes = checktreer(tree->lt_right, level + 1, context);
296 printf("%d:\tBad left side.\n", level);
302 printf("%d:\tBad right side.\n", level);
309 printf("%d:\tLeft and right reversed.\n", level);
311 if (tree->lt_dist != 1)
314 printf("%d:\tDistance incorrect.\n", level);
317 else if (rnodes == 0)
319 if (tree->lt_dist != 1)
322 printf("%d:\tDistance incorrect.\n", level);
325 else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist)
328 printf("%d:\tLeft and right reversed.\n", level);
329 if (tree->lt_dist != 1 + tree->lt_left->lt_dist)
330 printf("%d:\tDistance incorrect.\n", level);
332 else if (tree->lt_dist != 1 + tree->lt_right->lt_dist)
335 printf("%d:\tDistance incorrect.\n", level);
338 if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context))
341 printf("%d:\tLeft child < parent.\n");
344 if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context))
347 printf("%d:\tRight child < parent.\n");
350 return (-1 + -lnodes + -rnodes);
351 return (1 + lnodes + rnodes);