diff options
Diffstat (limited to 'src/backend/utils/sort/lselect.c')
-rw-r--r-- | src/backend/utils/sort/lselect.c | 525 |
1 files changed, 285 insertions, 240 deletions
diff --git a/src/backend/utils/sort/lselect.c b/src/backend/utils/sort/lselect.c index 6797bd40ca0..bc6948292b3 100644 --- a/src/backend/utils/sort/lselect.c +++ b/src/backend/utils/sort/lselect.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * lselect.c-- - * leftist tree selection algorithm (linked priority queue--Knuth, Vol.3, - * pp.150-52) + * leftist tree selection algorithm (linked priority queue--Knuth, Vol.3, + * pp.150-52) * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.5 1997/08/12 22:55:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.6 1997/09/07 04:54:16 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -26,295 +26,340 @@ #include "utils/psort.h" #include "utils/lselect.h" -#define PUTTUP(TUP, FP) fwrite((char *)TUP, (TUP)->t_len, 1, FP) +#define PUTTUP(TUP, FP) fwrite((char *)TUP, (TUP)->t_len, 1, FP) /* - * USEMEM - record use of memory - * FREEMEM - record freeing of memory + * USEMEM - record use of memory + * FREEMEM - record freeing of memory */ -#define USEMEM(context,AMT) context->sortMem -= (AMT) -#define FREEMEM(context,AMT) context->sortMem += (AMT) +#define USEMEM(context,AMT) context->sortMem -= (AMT) +#define FREEMEM(context,AMT) context->sortMem += (AMT) /* - * lmerge - merges two leftist trees into one + * lmerge - merges two leftist trees into one * - * Note: - * Enforcing the rule that pt->lt_dist >= qt->lt_dist may - * simplifify much of the code. Removing recursion will not - * speed up code significantly. + * Note: + * Enforcing the rule that pt->lt_dist >= qt->lt_dist may + * simplifify much of the code. Removing recursion will not + * speed up code significantly. */ struct leftist * -lmerge(struct leftist *pt, struct leftist *qt, LeftistContext context) +lmerge(struct leftist * pt, struct leftist * qt, LeftistContext context) { - register struct leftist *root, *majorLeftist, *minorLeftist; - int dist; - - if (tuplecmp(pt->lt_tuple, qt->lt_tuple, context)) { - root = pt; - majorLeftist = qt; - } else { - root = qt; - majorLeftist = pt; - } - if (root->lt_left == NULL) - root->lt_left = majorLeftist; - else { - if ((minorLeftist = root->lt_right) != NULL) - majorLeftist = lmerge(majorLeftist, minorLeftist, context); - if ((dist = root->lt_left->lt_dist) < majorLeftist->lt_dist) { - root->lt_dist = 1 + dist; - root->lt_right = root->lt_left; - root->lt_left = majorLeftist; - } else { - root->lt_dist = 1 + majorLeftist->lt_dist; - root->lt_right = majorLeftist; + register struct leftist *root, + *majorLeftist, + *minorLeftist; + int dist; + + if (tuplecmp(pt->lt_tuple, qt->lt_tuple, context)) + { + root = pt; + majorLeftist = qt; + } + else + { + root = qt; + majorLeftist = pt; } - } - return(root); + if (root->lt_left == NULL) + root->lt_left = majorLeftist; + else + { + if ((minorLeftist = root->lt_right) != NULL) + majorLeftist = lmerge(majorLeftist, minorLeftist, context); + if ((dist = root->lt_left->lt_dist) < majorLeftist->lt_dist) + { + root->lt_dist = 1 + dist; + root->lt_right = root->lt_left; + root->lt_left = majorLeftist; + } + else + { + root->lt_dist = 1 + majorLeftist->lt_dist; + root->lt_right = majorLeftist; + } + } + return (root); } static struct leftist * -linsert(struct leftist *root, struct leftist *new1, LeftistContext context) +linsert(struct leftist * root, struct leftist * new1, LeftistContext context) { - register struct leftist *left, *right; - - if (! tuplecmp(root->lt_tuple, new1->lt_tuple, context)) { - new1->lt_left = root; - return(new1); - } - left = root->lt_left; - right = root->lt_right; - if (right == NULL) { - if (left == NULL) - root->lt_left = new1; - else { - root->lt_right = new1; - root->lt_dist = 2; + register struct leftist *left, + *right; + + if (!tuplecmp(root->lt_tuple, new1->lt_tuple, context)) + { + new1->lt_left = root; + return (new1); + } + left = root->lt_left; + right = root->lt_right; + if (right == NULL) + { + if (left == NULL) + root->lt_left = new1; + else + { + root->lt_right = new1; + root->lt_dist = 2; + } + return (root); + } + right = linsert(right, new1, context); + if (right->lt_dist < left->lt_dist) + { + root->lt_dist = 1 + left->lt_dist; + root->lt_left = right; + root->lt_right = left; + } + else + { + root->lt_dist = 1 + right->lt_dist; + root->lt_right = right; } - return(root); - } - right = linsert(right, new1, context); - if (right->lt_dist < left->lt_dist) { - root->lt_dist = 1 + left->lt_dist; - root->lt_left = right; - root->lt_right = left; - } else { - root->lt_dist = 1 + right->lt_dist; - root->lt_right = right; - } - return(root); + return (root); } /* - * gettuple - returns tuple at top of tree (Tuples) + * gettuple - returns tuple at top of tree (Tuples) * - * Returns: - * tuple at top of tree, NULL if failed ALLOC() - * *devnum is set to the devnum of tuple returned - * *treep is set to the new tree + * Returns: + * tuple at top of tree, NULL if failed ALLOC() + * *devnum is set to the devnum of tuple returned + * *treep is set to the new tree * - * Note: - * *treep must not be NULL - * NULL is currently never returned BUG + * Note: + * *treep must not be NULL + * NULL is currently never returned BUG */ HeapTuple -gettuple(struct leftist **treep, - short *devnum, /* device from which tuple came */ - LeftistContext context) +gettuple(struct leftist ** treep, + short *devnum, /* device from which tuple came */ + LeftistContext context) { - register struct leftist *tp; - HeapTuple tup; - - tp = *treep; - tup = tp->lt_tuple; - *devnum = tp->lt_devnum; - if (tp->lt_dist == 1) /* lt_left == NULL */ - *treep = tp->lt_left; - else - *treep = lmerge(tp->lt_left, tp->lt_right, context); - - FREEMEM(context,sizeof (struct leftist)); - FREE(tp); - return(tup); + register struct leftist *tp; + HeapTuple tup; + + tp = *treep; + tup = tp->lt_tuple; + *devnum = tp->lt_devnum; + if (tp->lt_dist == 1) /* lt_left == NULL */ + *treep = tp->lt_left; + else + *treep = lmerge(tp->lt_left, tp->lt_right, context); + + FREEMEM(context, sizeof(struct leftist)); + FREE(tp); + return (tup); } /* - * puttuple - inserts new tuple into tree + * puttuple - inserts new tuple into tree * - * Returns: - * NULL iff failed ALLOC() + * Returns: + * NULL iff failed ALLOC() * - * Note: - * Currently never returns NULL BUG + * Note: + * Currently never returns NULL BUG */ void -puttuple(struct leftist **treep, - HeapTuple newtuple, - short devnum, - LeftistContext context) +puttuple(struct leftist ** treep, + HeapTuple newtuple, + short devnum, + LeftistContext context) { - register struct leftist *new1; - register struct leftist *tp; - - new1 = (struct leftist *) palloc((unsigned) sizeof (struct leftist)); - USEMEM(context,sizeof (struct leftist)); - new1->lt_dist = 1; - new1->lt_devnum = devnum; - new1->lt_tuple = newtuple; - new1->lt_left = NULL; - new1->lt_right = NULL; - if ((tp = *treep) == NULL) - *treep = new1; - else - *treep = linsert(tp, new1, context); - return; + register struct leftist *new1; + register struct leftist *tp; + + new1 = (struct leftist *) palloc((unsigned) sizeof(struct leftist)); + USEMEM(context, sizeof(struct leftist)); + new1->lt_dist = 1; + new1->lt_devnum = devnum; + new1->lt_tuple = newtuple; + new1->lt_left = NULL; + new1->lt_right = NULL; + if ((tp = *treep) == NULL) + *treep = new1; + else + *treep = linsert(tp, new1, context); + return; } /* - * tuplecmp - Compares two tuples with respect CmpList + * tuplecmp - Compares two tuples with respect CmpList * - * Returns: - * 1 if left < right ;0 otherwise - * Assumtions: + * Returns: + * 1 if left < right ;0 otherwise + * Assumtions: */ int tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context) { - register char *lattr, *rattr; - int nkey = 0; - int result = 0; - bool isnull; - - if (ltup == (HeapTuple)NULL) - return(0); - if (rtup == (HeapTuple)NULL) - return(1); - while (nkey < context->nKeys && !result) { - lattr = heap_getattr(ltup, InvalidBuffer, - context->scanKeys[nkey].sk_attno, - context->tupDesc, &isnull); - if (isnull) - return(0); - rattr = heap_getattr(rtup, InvalidBuffer, - context->scanKeys[nkey].sk_attno, - context->tupDesc, - &isnull); - if (isnull) - return(1); - if (context->scanKeys[nkey].sk_flags & SK_COMMUTE) { - if (!(result = - (long) (*context->scanKeys[nkey].sk_func) (rattr, lattr))) - result = - -(long) (*context->scanKeys[nkey].sk_func) (lattr, rattr); - } else if (!(result = - (long) (*context->scanKeys[nkey].sk_func) (lattr, rattr))) - result = - -(long) (*context->scanKeys[nkey].sk_func) (rattr, lattr); - nkey++; - } - return (result == 1); + register char *lattr, + *rattr; + int nkey = 0; + int result = 0; + bool isnull; + + if (ltup == (HeapTuple) NULL) + return (0); + if (rtup == (HeapTuple) NULL) + return (1); + while (nkey < context->nKeys && !result) + { + lattr = heap_getattr(ltup, InvalidBuffer, + context->scanKeys[nkey].sk_attno, + context->tupDesc, &isnull); + if (isnull) + return (0); + rattr = heap_getattr(rtup, InvalidBuffer, + context->scanKeys[nkey].sk_attno, + context->tupDesc, + &isnull); + if (isnull) + return (1); + if (context->scanKeys[nkey].sk_flags & SK_COMMUTE) + { + if (!(result = + (long) (*context->scanKeys[nkey].sk_func) (rattr, lattr))) + result = + -(long) (*context->scanKeys[nkey].sk_func) (lattr, rattr); + } + else if (!(result = + (long) (*context->scanKeys[nkey].sk_func) (lattr, rattr))) + result = + -(long) (*context->scanKeys[nkey].sk_func) (rattr, lattr); + nkey++; + } + return (result == 1); } #ifdef EBUG void -checktree(struct leftist *tree, LeftistContext context) +checktree(struct leftist * tree, LeftistContext context) { - int lnodes; - int rnodes; - - if (tree == NULL) { - puts("Null tree."); - return; - } - lnodes = checktreer(tree->lt_left, 1, context); - rnodes = checktreer(tree->lt_right, 1, context); - if (lnodes < 0) { - lnodes = -lnodes; - puts("0:\tBad left side."); - } - if (rnodes < 0) { - rnodes = -rnodes; - puts("0:\tBad right side."); - } - if (lnodes == 0) { - if (rnodes != 0) - puts("0:\tLeft and right reversed."); - if (tree->lt_dist != 1) - puts("0:\tDistance incorrect."); - } else if (rnodes == 0) { - if (tree->lt_dist != 1) - puts("0:\tDistance incorrect."); - } else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist) { - puts("0:\tLeft and right reversed."); - if (tree->lt_dist != 1 + tree->lt_left->lt_dist) - puts("0:\tDistance incorrect."); - } else if (tree->lt_dist != 1+ tree->lt_right->lt_dist) - puts("0:\tDistance incorrect."); - if (lnodes > 0) - if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) - printf("%d:\tLeft child < parent.\n"); - if (rnodes > 0) - if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) - printf("%d:\tRight child < parent.\n"); - printf("Tree has %d nodes\n", 1 + lnodes + rnodes); + int lnodes; + int rnodes; + + if (tree == NULL) + { + puts("Null tree."); + return; + } + lnodes = checktreer(tree->lt_left, 1, context); + rnodes = checktreer(tree->lt_right, 1, context); + if (lnodes < 0) + { + lnodes = -lnodes; + puts("0:\tBad left side."); + } + if (rnodes < 0) + { + rnodes = -rnodes; + puts("0:\tBad right side."); + } + if (lnodes == 0) + { + if (rnodes != 0) + puts("0:\tLeft and right reversed."); + if (tree->lt_dist != 1) + puts("0:\tDistance incorrect."); + } + else if (rnodes == 0) + { + if (tree->lt_dist != 1) + puts("0:\tDistance incorrect."); + } + else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist) + { + puts("0:\tLeft and right reversed."); + if (tree->lt_dist != 1 + tree->lt_left->lt_dist) + puts("0:\tDistance incorrect."); + } + else if (tree->lt_dist != 1 + tree->lt_right->lt_dist) + puts("0:\tDistance incorrect."); + if (lnodes > 0) + if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) + printf("%d:\tLeft child < parent.\n"); + if (rnodes > 0) + if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) + printf("%d:\tRight child < parent.\n"); + printf("Tree has %d nodes\n", 1 + lnodes + rnodes); } int -checktreer(struct leftist *tree, int level, LeftistContext context) +checktreer(struct leftist * tree, int level, LeftistContext context) { - int lnodes, rnodes; - int error = 0; - - if (tree == NULL) - return(0); - lnodes = checktreer(tree->lt_left, level + 1, context); - rnodes = checktreer(tree->lt_right, level + 1, context); - if (lnodes < 0) { - error = 1; - lnodes = -lnodes; - printf("%d:\tBad left side.\n", level); - } - if (rnodes < 0) { - error = 1; - rnodes = -rnodes; - printf("%d:\tBad right side.\n", level); - } - if (lnodes == 0) { - if (rnodes != 0) { - error = 1; - printf("%d:\tLeft and right reversed.\n", level); + int lnodes, + rnodes; + int error = 0; + + if (tree == NULL) + return (0); + lnodes = checktreer(tree->lt_left, level + 1, context); + rnodes = checktreer(tree->lt_right, level + 1, context); + if (lnodes < 0) + { + error = 1; + lnodes = -lnodes; + printf("%d:\tBad left side.\n", level); } - if (tree->lt_dist != 1) { - error = 1; - printf("%d:\tDistance incorrect.\n", level); + if (rnodes < 0) + { + error = 1; + rnodes = -rnodes; + printf("%d:\tBad right side.\n", level); } - } else if (rnodes == 0) { - if (tree->lt_dist != 1) { - error = 1; - printf("%d:\tDistance incorrect.\n", level); - } - } else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist) { - error = 1; - printf("%d:\tLeft and right reversed.\n", level); - if (tree->lt_dist != 1 + tree->lt_left->lt_dist) - printf("%d:\tDistance incorrect.\n", level); - } else if (tree->lt_dist != 1+ tree->lt_right->lt_dist) { - error = 1; - printf("%d:\tDistance incorrect.\n", level); - } - if (lnodes > 0) - if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) { - error = 1; - printf("%d:\tLeft child < parent.\n"); + if (lnodes == 0) + { + if (rnodes != 0) + { + error = 1; + printf("%d:\tLeft and right reversed.\n", level); + } + if (tree->lt_dist != 1) + { + error = 1; + printf("%d:\tDistance incorrect.\n", level); + } } - if (rnodes > 0) - if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) { - error = 1; - printf("%d:\tRight child < parent.\n"); + else if (rnodes == 0) + { + if (tree->lt_dist != 1) + { + error = 1; + printf("%d:\tDistance incorrect.\n", level); + } } - if (error) - return(-1 + -lnodes + -rnodes); - return(1 + lnodes + rnodes); + else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist) + { + error = 1; + printf("%d:\tLeft and right reversed.\n", level); + if (tree->lt_dist != 1 + tree->lt_left->lt_dist) + printf("%d:\tDistance incorrect.\n", level); + } + else if (tree->lt_dist != 1 + tree->lt_right->lt_dist) + { + error = 1; + printf("%d:\tDistance incorrect.\n", level); + } + if (lnodes > 0) + if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) + { + error = 1; + printf("%d:\tLeft child < parent.\n"); + } + if (rnodes > 0) + if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) + { + error = 1; + printf("%d:\tRight child < parent.\n"); + } + if (error) + return (-1 + -lnodes + -rnodes); + return (1 + lnodes + rnodes); } + #endif |