diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 1999-07-10 18:21:59 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 1999-07-10 18:21:59 +0000 |
commit | cc62dc2032159e2bb7c7008a28f7d0777e0cc22f (patch) | |
tree | 44d1cb69e302db1ea724d800d99fd74ae06706c4 /src | |
parent | bc5f34c89ef416ae3be8c7cb4bc063a6cac5eb15 (diff) | |
download | postgresql-cc62dc2032159e2bb7c7008a28f7d0777e0cc22f.tar.gz postgresql-cc62dc2032159e2bb7c7008a28f7d0777e0cc22f.zip |
Fix tuplecmp() to ensure repeatable sort ordering of tuples
that contain null fields. Old code would produce erratic sort results
because comparisons of tuples containing nulls could produce inconsistent
answers.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/sort/lselect.c | 56 |
1 files changed, 32 insertions, 24 deletions
diff --git a/src/backend/utils/sort/lselect.c b/src/backend/utils/sort/lselect.c index 230b0b0e9cc..ae10049b961 100644 --- a/src/backend/utils/sort/lselect.c +++ b/src/backend/utils/sort/lselect.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.15 1999/02/13 23:20:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.16 1999/07/10 18:21:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -186,41 +186,49 @@ puttuple(struct leftist ** treep, int tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context) { - Datum lattr, - rattr; - int nkey = 0; + int nkey; int result = 0; - bool isnull; if (ltup == (HeapTuple) NULL) return 0; if (rtup == (HeapTuple) NULL) return 1; - while (nkey < context->nKeys && !result) + for (nkey = 0; nkey < context->nKeys; nkey++) { - lattr = heap_getattr(ltup, - context->scanKeys[nkey].sk_attno, - context->tupDesc, &isnull); - if (isnull) - return 0; - rattr = heap_getattr(rtup, - context->scanKeys[nkey].sk_attno, - context->tupDesc, - &isnull); - if (isnull) + 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 (context->scanKeys[nkey].sk_flags & SK_COMMUTE) + 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(&context->scanKeys[nkey].sk_func)) (rattr, lattr))) + (long) (*fmgr_faddr(&thisKey->sk_func)) (lattr, rattr))) result = - -(long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (lattr, rattr); + -(long) (*fmgr_faddr(&thisKey->sk_func)) (rattr, lattr); } - else if (!(result = - (long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (lattr, rattr))) - result = - -(long) (*fmgr_faddr(&context->scanKeys[nkey].sk_func)) (rattr, lattr); - nkey++; + if (result) + break; } return result == 1; } |