mirror of https://github.com/postgres/postgres
parent
26c48b5e8c
commit
887afac1f5
@ -1,355 +0,0 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* lselect.c |
||||
* 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.19 1999/07/17 20:18:16 momjian Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
|
||||
#include "access/heapam.h" |
||||
#include "utils/lselect.h" |
||||
|
||||
/*
|
||||
* 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. |
||||
*/ |
||||
struct leftist * |
||||
lmerge(struct leftist * pt, struct leftist * qt, LeftistContext context) |
||||
{ |
||||
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; |
||||
} |
||||
} |
||||
return root; |
||||
} |
||||
|
||||
static struct leftist * |
||||
linsert(struct leftist * root, struct leftist * new1, LeftistContext context) |
||||
{ |
||||
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; |
||||
} |
||||
|
||||
/*
|
||||
* 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 |
||||
* |
||||
* 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) |
||||
{ |
||||
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); |
||||
|
||||
pfree(tp); |
||||
return tup; |
||||
} |
||||
|
||||
/*
|
||||
* puttuple - inserts new tuple into tree |
||||
* |
||||
* Returns: |
||||
* NULL iff failed ALLOC() |
||||
* |
||||
* Note: |
||||
* Currently never returns NULL BUG |
||||
*/ |
||||
void |
||||
puttuple(struct leftist ** treep, |
||||
HeapTuple newtuple, |
||||
short devnum, |
||||
LeftistContext context) |
||||
{ |
||||
struct leftist *new1; |
||||
struct leftist *tp; |
||||
|
||||
new1 = (struct leftist *) palloc((unsigned) 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 |
||||
* |
||||
* Returns: |
||||
* 1 if left < right ;0 otherwise |
||||
* Assumtions: |
||||
*/ |
||||
int |
||||
tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context) |
||||
{ |
||||
int nkey; |
||||
int result = 0; |
||||
|
||||
if (ltup == (HeapTuple) NULL) |
||||
return 0; |
||||
if (rtup == (HeapTuple) NULL) |
||||
return 1; |
||||
for (nkey = 0; nkey < context->nKeys; nkey++) |
||||
{ |
||||
ScanKey thisKey = & context->scanKeys[nkey]; |
||||
Datum lattr, |
||||
rattr; |
||||
bool lisnull, |
||||
risnull; |
||||
|
||||
lattr = heap_getattr(ltup, thisKey->sk_attno, |
||||
context->tupDesc, &lisnull); |
||||
rattr = heap_getattr(rtup, thisKey->sk_attno, |
||||
context->tupDesc, &risnull); |
||||
if (lisnull) |
||||
{ |
||||
if (risnull) |
||||
continue; /* treat two nulls as equal */ |
||||
return 0; /* else, a null sorts after all else */ |
||||
} |
||||
if (risnull) |
||||
return 1; |
||||
if (thisKey->sk_flags & SK_COMMUTE) |
||||
{ |
||||
if (!(result = |
||||
(long) (*fmgr_faddr(&thisKey->sk_func)) (rattr, lattr))) |
||||
result = |
||||
-(long) (*fmgr_faddr(&thisKey->sk_func)) (lattr, rattr); |
||||
} |
||||
else |
||||
{ |
||||
if (!(result = |
||||
(long) (*fmgr_faddr(&thisKey->sk_func)) (lattr, rattr))) |
||||
result = |
||||
-(long) (*fmgr_faddr(&thisKey->sk_func)) (rattr, lattr); |
||||
} |
||||
if (result) |
||||
break; |
||||
} |
||||
return result == 1; |
||||
} |
||||
|
||||
#ifdef EBUG |
||||
void |
||||
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 |
||||
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); |
||||
} |
||||
if (tree->lt_dist != 1) |
||||
{ |
||||
error = 1; |
||||
printf("%d:\tDistance incorrect.\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 (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 |
File diff suppressed because it is too large
Load Diff
@ -1,22 +0,0 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* qsort.h |
||||
* |
||||
* |
||||
* |
||||
* Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* $Id: qsort.h,v 1.7 1999/02/13 23:21:32 momjian Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef QSORT_H |
||||
#define QSORT_H |
||||
|
||||
|
||||
extern void pg_qsort(void *bot, |
||||
size_t nmemb, |
||||
size_t size, |
||||
int (*compar) (void *, void *)); |
||||
|
||||
#endif /* QSORT_H */ |
@ -1,51 +0,0 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* lselect.h |
||||
* definitions for the replacement selection algorithm. |
||||
* |
||||
* |
||||
* Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* $Id: lselect.h,v 1.14 1999/07/17 20:18:36 momjian Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef LSELECT_H |
||||
#define LSELECT_H |
||||
|
||||
#include "utils/syscache.h" |
||||
|
||||
struct leftist |
||||
{ |
||||
short lt_dist; /* distance to leaf/empty node */ |
||||
short lt_devnum; /* device number of tuple */ |
||||
HeapTuple lt_tuple; |
||||
struct leftist *lt_left; |
||||
struct leftist *lt_right; |
||||
}; |
||||
|
||||
/* replaces global variables in lselect.c to make it reentrant */ |
||||
typedef struct |
||||
{ |
||||
TupleDesc tupDesc; |
||||
int nKeys; |
||||
ScanKey scanKeys; |
||||
int sortMem; /* needed for psort */ |
||||
} LeftistContextData; |
||||
typedef LeftistContextData *LeftistContext; |
||||
|
||||
extern struct leftist *lmerge(struct leftist * pt, struct leftist * qt, |
||||
LeftistContext context); |
||||
extern HeapTuple gettuple(struct leftist ** treep, short *devnum, |
||||
LeftistContext context); |
||||
extern void puttuple(struct leftist ** treep, HeapTuple newtuple, short devnum, |
||||
LeftistContext context); |
||||
extern int tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context); |
||||
|
||||
#ifdef EBUG |
||||
extern void checktree(struct leftist * tree, LeftistContext context); |
||||
extern int checktreer(struct leftist * tree, int level, LeftistContext context); |
||||
|
||||
#endif /* EBUG */ |
||||
|
||||
#endif /* LSELECT_H */ |
@ -1,26 +0,0 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* psort.h |
||||
* Polyphase merge sort. |
||||
* |
||||
* Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* $Id: psort.h,v 1.23 1999/10/16 19:49:28 tgl Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef PSORT_H |
||||
#define PSORT_H |
||||
|
||||
#include "access/htup.h" |
||||
#include "access/skey.h" |
||||
#include "nodes/plannodes.h" |
||||
|
||||
extern bool psort_begin(Sort *node, int nkeys, ScanKey key); |
||||
extern HeapTuple psort_grabtuple(Sort *node, bool *should_free); |
||||
extern void psort_markpos(Sort *node); |
||||
extern void psort_restorepos(Sort *node); |
||||
extern void psort_end(Sort *node); |
||||
extern void psort_rescan(Sort *node); |
||||
|
||||
#endif /* PSORT_H */ |
Loading…
Reference in new issue