summaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-02-18 06:32:39 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-02-18 06:32:39 +0000
commit8cb624262abdc194616aaf89e1ab48cdc63e5cc2 (patch)
treea0276eb3e75544057ffe101076cfeb18a8ba2efb /src/backend/utils
parent49353692d11ba384d0b4e58a6932481357d64153 (diff)
downloadpostgresql-8cb624262abdc194616aaf89e1ab48cdc63e5cc2.tar.gz
Replace inefficient _bt_invokestrat calls with direct calls to the
appropriate btree three-way comparison routine. Not clear why the three-way comparison routines were being used in some paths and not others in btree --- incomplete changes by someone long ago, maybe? Anyway, this makes for a nice speedup in CREATE INDEX.
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/sort/tuplesort.c79
1 files changed, 49 insertions, 30 deletions
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 1d0ed4e9f2..be80b246a2 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -78,7 +78,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.5 2000/01/26 05:57:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.6 2000/02/18 06:32:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -253,6 +253,7 @@ struct Tuplesortstate
* by tuplesort_begin_index and used only by the IndexTuple routines.
*/
Relation indexRel;
+ ScanKey indexScanKey;
bool enforceUnique; /* complain if we find duplicate tuples */
/*
@@ -476,6 +477,8 @@ tuplesort_begin_index(Relation indexRel,
state->tuplesize = tuplesize_index;
state->indexRel = indexRel;
+ /* see comments below about btree dependence of this code... */
+ state->indexScanKey = _bt_mkscankey_nodata(indexRel);
state->enforceUnique = enforceUnique;
return state;
@@ -1745,40 +1748,56 @@ tuplesize_heap(Tuplesortstate *state, void *tup)
static int
comparetup_index(Tuplesortstate *state, const void *a, const void *b)
{
- IndexTuple ltup = (IndexTuple) a;
- IndexTuple rtup = (IndexTuple) b;
- TupleDesc itdesc = state->indexRel->rd_att;
- bool equal_isnull = false;
+ /*
+ * This is almost the same as _bt_tuplecompare(), but we need to
+ * keep track of whether any null fields are present.
+ */
+ IndexTuple tuple1 = (IndexTuple) a;
+ IndexTuple tuple2 = (IndexTuple) b;
+ Relation rel = state->indexRel;
+ Size keysz = RelationGetNumberOfAttributes(rel);
+ ScanKey scankey = state->indexScanKey;
+ TupleDesc tupDes;
int i;
+ bool equal_hasnull = false;
- for (i = 1; i <= itdesc->natts; i++)
- {
- Datum lattr,
- rattr;
- bool isnull1,
- isnull2;
-
- lattr = index_getattr(ltup, i, itdesc, &isnull1);
- rattr = index_getattr(rtup, i, itdesc, &isnull2);
+ tupDes = RelationGetDescr(rel);
- if (isnull1)
+ for (i = 1; i <= keysz; i++)
+ {
+ ScanKey entry = &scankey[i - 1];
+ Datum attrDatum1,
+ attrDatum2;
+ bool isFirstNull,
+ isSecondNull;
+ int32 compare;
+
+ attrDatum1 = index_getattr(tuple1, i, tupDes, &isFirstNull);
+ attrDatum2 = index_getattr(tuple2, i, tupDes, &isSecondNull);
+
+ /* see comments about NULLs handling in btbuild */
+ if (isFirstNull) /* attr in tuple1 is NULL */
{
- if (!isnull2)
- return 1; /* NULL sorts after non-NULL */
- equal_isnull = true;
- continue;
+ if (isSecondNull) /* attr in tuple2 is NULL too */
+ {
+ compare = 0;
+ equal_hasnull = true;
+ }
+ else
+ compare = 1; /* NULL ">" not-NULL */
+ }
+ else if (isSecondNull) /* attr in tuple1 is NOT_NULL and */
+ { /* attr in tuple2 is NULL */
+ compare = -1; /* not-NULL "<" NULL */
+ }
+ else
+ {
+ compare = (int32) FMGR_PTR2(&entry->sk_func,
+ attrDatum1, attrDatum2);
}
- else if (isnull2)
- return -1;
- if (_bt_invokestrat(state->indexRel, i,
- BTGreaterStrategyNumber,
- lattr, rattr))
- return 1;
- if (_bt_invokestrat(state->indexRel, i,
- BTGreaterStrategyNumber,
- rattr, lattr))
- return -1;
+ if (compare != 0)
+ return (int) compare; /* done when we find unequal attributes */
}
/*
@@ -1790,7 +1809,7 @@ comparetup_index(Tuplesortstate *state, const void *a, const void *b)
* the sort algorithm wouldn't have checked whether one must appear
* before the other.
*/
- if (state->enforceUnique && !equal_isnull)
+ if (state->enforceUnique && !equal_hasnull)
elog(ERROR, "Cannot create unique index. Table contains non-unique values");
return 0;