aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/nbtree/nbtutils.c')
-rw-r--r--src/backend/access/nbtree/nbtutils.c623
1 files changed, 320 insertions, 303 deletions
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 738e55dbccd..096f1d2691e 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* btutils.c--
- * Utility code for Postgres btree implementation.
+ * Utility code for Postgres btree implementation.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.11 1997/08/19 21:29:47 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.12 1997/09/07 04:39:05 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,367 +23,384 @@
#include <catalog/pg_proc.h>
#include <executor/execdebug.h>
-extern int NIndexTupleProcessed;
+extern int NIndexTupleProcessed;
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
-ScanKey
+ScanKey
_bt_mkscankey(Relation rel, IndexTuple itup)
-{
- ScanKey skey;
- TupleDesc itupdesc;
- int natts;
- int i;
- Datum arg;
- RegProcedure proc;
- bool null;
- bits16 flag;
-
- natts = rel->rd_rel->relnatts;
- itupdesc = RelationGetTupleDescriptor(rel);
-
- skey = (ScanKey) palloc(natts * sizeof(ScanKeyData));
-
- for (i = 0; i < natts; i++) {
- arg = index_getattr(itup, i + 1, itupdesc, &null);
- if ( null )
- {
- proc = NullValueRegProcedure;
- flag = SK_ISNULL;
- }
- else
+{
+ ScanKey skey;
+ TupleDesc itupdesc;
+ int natts;
+ int i;
+ Datum arg;
+ RegProcedure proc;
+ bool null;
+ bits16 flag;
+
+ natts = rel->rd_rel->relnatts;
+ itupdesc = RelationGetTupleDescriptor(rel);
+
+ skey = (ScanKey) palloc(natts * sizeof(ScanKeyData));
+
+ for (i = 0; i < natts; i++)
{
- proc = index_getprocid(rel, i + 1, BTORDER_PROC);
- flag = 0x0;
+ arg = index_getattr(itup, i + 1, itupdesc, &null);
+ if (null)
+ {
+ proc = NullValueRegProcedure;
+ flag = SK_ISNULL;
+ }
+ else
+ {
+ proc = index_getprocid(rel, i + 1, BTORDER_PROC);
+ flag = 0x0;
+ }
+ ScanKeyEntryInitialize(&skey[i],
+ flag, (AttrNumber) (i + 1), proc, arg);
}
- ScanKeyEntryInitialize(&skey[i],
- flag, (AttrNumber) (i + 1), proc, arg);
- }
-
- return (skey);
+
+ return (skey);
}
void
_bt_freeskey(ScanKey skey)
{
- pfree(skey);
+ pfree(skey);
}
void
_bt_freestack(BTStack stack)
{
- BTStack ostack;
-
- while (stack != (BTStack) NULL) {
- ostack = stack;
- stack = stack->bts_parent;
- pfree(ostack->bts_btitem);
- pfree(ostack);
- }
+ BTStack ostack;
+
+ while (stack != (BTStack) NULL)
+ {
+ ostack = stack;
+ stack = stack->bts_parent;
+ pfree(ostack->bts_btitem);
+ pfree(ostack);
+ }
}
/*
- * _bt_orderkeys() -- Put keys in a sensible order for conjunctive quals.
+ * _bt_orderkeys() -- Put keys in a sensible order for conjunctive quals.
*
- * The order of the keys in the qual match the ordering imposed by
- * the index. This routine only needs to be called if there are
- * more than one qual clauses using this index.
+ * The order of the keys in the qual match the ordering imposed by
+ * the index. This routine only needs to be called if there are
+ * more than one qual clauses using this index.
*/
void
_bt_orderkeys(Relation relation, BTScanOpaque so)
{
- ScanKey xform;
- ScanKeyData *cur;
- StrategyMap map;
- int nbytes;
- long test;
- int i, j;
- int init[BTMaxStrategyNumber+1];
- ScanKey key;
- uint16 numberOfKeys = so->numberOfKeys;
- uint16 new_numberOfKeys = 0;
- AttrNumber attno = 1;
-
- if ( numberOfKeys < 1 )
- return;
-
- key = so->keyData;
-
- cur = &key[0];
- if ( cur->sk_attno != 1 )
- elog (WARN, "_bt_orderkeys: key(s) for attribute 1 missed");
-
- if ( numberOfKeys == 1 )
- {
- /*
- * We don't use indices for 'A is null' and 'A is not null'
- * currently and 'A < = > <> NULL' is non-sense' - so
- * qual is not Ok. - vadim 03/21/97
- */
- if ( cur->sk_flags & SK_ISNULL )
- so->qual_ok = 0;
- so->numberOfFirstKeys = 1;
- return;
- }
-
- /* get space for the modified array of keys */
- nbytes = BTMaxStrategyNumber * sizeof(ScanKeyData);
- xform = (ScanKey) palloc(nbytes);
-
- memset(xform, 0, nbytes);
- map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
- BTMaxStrategyNumber,
- attno);
- for (j = 0; j <= BTMaxStrategyNumber; j++)
- init[j] = 0;
-
- /* check each key passed in */
- for (i = 0; ; )
- {
- if ( i < numberOfKeys )
- cur = &key[i];
-
- if ( cur->sk_flags & SK_ISNULL ) /* see comments above */
- so->qual_ok = 0;
-
- if ( i == numberOfKeys || cur->sk_attno != attno )
+ ScanKey xform;
+ ScanKeyData *cur;
+ StrategyMap map;
+ int nbytes;
+ long test;
+ int i,
+ j;
+ int init[BTMaxStrategyNumber + 1];
+ ScanKey key;
+ uint16 numberOfKeys = so->numberOfKeys;
+ uint16 new_numberOfKeys = 0;
+ AttrNumber attno = 1;
+
+ if (numberOfKeys < 1)
+ return;
+
+ key = so->keyData;
+
+ cur = &key[0];
+ if (cur->sk_attno != 1)
+ elog(WARN, "_bt_orderkeys: key(s) for attribute 1 missed");
+
+ if (numberOfKeys == 1)
{
- if ( cur->sk_attno != attno + 1 && i < numberOfKeys )
- {
- elog (WARN, "_bt_orderkeys: key(s) for attribute %d missed", attno + 1);
- }
- /*
- * If = has been specified, no other key will be used.
- * In case of key < 2 && key == 1 and so on
- * we have to set qual_ok to 0
- */
- if (init[BTEqualStrategyNumber - 1])
- {
- ScanKeyData *eq, *chk;
-
- eq = &xform[BTEqualStrategyNumber - 1];
- for (j = BTMaxStrategyNumber; --j >= 0; )
- {
- if ( j == (BTEqualStrategyNumber - 1) || init[j] == 0 )
- continue;
- chk = &xform[j];
- test = (long) fmgr(chk->sk_procedure, eq->sk_argument, chk->sk_argument);
- if (!test)
- so->qual_ok = 0;
- }
- init[BTLessStrategyNumber - 1] = 0;
- init[BTLessEqualStrategyNumber - 1] = 0;
- init[BTGreaterEqualStrategyNumber - 1] = 0;
- init[BTGreaterStrategyNumber - 1] = 0;
- }
-
- /* only one of <, <= */
- if (init[BTLessStrategyNumber - 1]
- && init[BTLessEqualStrategyNumber - 1])
- {
- ScanKeyData *lt, *le;
-
- lt = &xform[BTLessStrategyNumber - 1];
- le = &xform[BTLessEqualStrategyNumber - 1];
+
/*
- * DO NOT use the cached function stuff here -- this is key
- * ordering, happens only when the user expresses a hokey
- * qualification, and gets executed only once, anyway. The
- * transform maps are hard-coded, and can't be initialized
- * in the correct way.
+ * We don't use indices for 'A is null' and 'A is not null'
+ * currently and 'A < = > <> NULL' is non-sense' - so qual is not
+ * Ok. - vadim 03/21/97
*/
- test = (long) fmgr(le->sk_procedure, lt->sk_argument, le->sk_argument);
- if (test)
- init[BTLessEqualStrategyNumber - 1] = 0;
- else
- init[BTLessStrategyNumber - 1] = 0;
- }
-
- /* only one of >, >= */
- if (init[BTGreaterStrategyNumber - 1]
- && init[BTGreaterEqualStrategyNumber - 1])
- {
- ScanKeyData *gt, *ge;
-
- gt = &xform[BTGreaterStrategyNumber - 1];
- ge = &xform[BTGreaterEqualStrategyNumber - 1];
-
- /* see note above on function cache */
- test = (long) fmgr(ge->sk_procedure, gt->sk_argument, ge->sk_argument);
- if (test)
- init[BTGreaterEqualStrategyNumber - 1] = 0;
- else
- init[BTGreaterStrategyNumber - 1] = 0;
- }
-
- /* okay, reorder and count */
- for (j = BTMaxStrategyNumber; --j >= 0; )
- if (init[j])
- key[new_numberOfKeys++] = xform[j];
-
- if ( attno == 1 )
- so->numberOfFirstKeys = new_numberOfKeys;
-
- if ( i == numberOfKeys )
- break;
-
- /* initialization for new attno */
- attno = cur->sk_attno;
- memset(xform, 0, nbytes);
- map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
- BTMaxStrategyNumber,
- attno);
- /* haven't looked at any strategies yet */
- for (j = 0; j <= BTMaxStrategyNumber; j++)
- init[j] = 0;
+ if (cur->sk_flags & SK_ISNULL)
+ so->qual_ok = 0;
+ so->numberOfFirstKeys = 1;
+ return;
}
- for (j = BTMaxStrategyNumber; --j >= 0; )
- {
- if (cur->sk_procedure == map->entry[j].sk_procedure)
- break;
- }
-
- /* have we seen one of these before? */
- if (init[j])
- {
- /* yup, use the appropriate value */
- test =
- (long) FMGR_PTR2(cur->sk_func, cur->sk_procedure,
- cur->sk_argument, xform[j].sk_argument);
- if (test)
- xform[j].sk_argument = cur->sk_argument;
- else if ( j == (BTEqualStrategyNumber - 1) )
- so->qual_ok = 0; /* key == a && key == b, but a != b */
- } else
+ /* get space for the modified array of keys */
+ nbytes = BTMaxStrategyNumber * sizeof(ScanKeyData);
+ xform = (ScanKey) palloc(nbytes);
+
+ memset(xform, 0, nbytes);
+ map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
+ BTMaxStrategyNumber,
+ attno);
+ for (j = 0; j <= BTMaxStrategyNumber; j++)
+ init[j] = 0;
+
+ /* check each key passed in */
+ for (i = 0;;)
{
- /* nope, use this value */
- memmove(&xform[j], cur, sizeof(*cur));
- init[j] = 1;
+ if (i < numberOfKeys)
+ cur = &key[i];
+
+ if (cur->sk_flags & SK_ISNULL) /* see comments above */
+ so->qual_ok = 0;
+
+ if (i == numberOfKeys || cur->sk_attno != attno)
+ {
+ if (cur->sk_attno != attno + 1 && i < numberOfKeys)
+ {
+ elog(WARN, "_bt_orderkeys: key(s) for attribute %d missed", attno + 1);
+ }
+
+ /*
+ * If = has been specified, no other key will be used. In case
+ * of key < 2 && key == 1 and so on we have to set qual_ok to
+ * 0
+ */
+ if (init[BTEqualStrategyNumber - 1])
+ {
+ ScanKeyData *eq,
+ *chk;
+
+ eq = &xform[BTEqualStrategyNumber - 1];
+ for (j = BTMaxStrategyNumber; --j >= 0;)
+ {
+ if (j == (BTEqualStrategyNumber - 1) || init[j] == 0)
+ continue;
+ chk = &xform[j];
+ test = (long) fmgr(chk->sk_procedure, eq->sk_argument, chk->sk_argument);
+ if (!test)
+ so->qual_ok = 0;
+ }
+ init[BTLessStrategyNumber - 1] = 0;
+ init[BTLessEqualStrategyNumber - 1] = 0;
+ init[BTGreaterEqualStrategyNumber - 1] = 0;
+ init[BTGreaterStrategyNumber - 1] = 0;
+ }
+
+ /* only one of <, <= */
+ if (init[BTLessStrategyNumber - 1]
+ && init[BTLessEqualStrategyNumber - 1])
+ {
+ ScanKeyData *lt,
+ *le;
+
+ lt = &xform[BTLessStrategyNumber - 1];
+ le = &xform[BTLessEqualStrategyNumber - 1];
+
+ /*
+ * DO NOT use the cached function stuff here -- this is
+ * key ordering, happens only when the user expresses a
+ * hokey qualification, and gets executed only once,
+ * anyway. The transform maps are hard-coded, and can't
+ * be initialized in the correct way.
+ */
+ test = (long) fmgr(le->sk_procedure, lt->sk_argument, le->sk_argument);
+ if (test)
+ init[BTLessEqualStrategyNumber - 1] = 0;
+ else
+ init[BTLessStrategyNumber - 1] = 0;
+ }
+
+ /* only one of >, >= */
+ if (init[BTGreaterStrategyNumber - 1]
+ && init[BTGreaterEqualStrategyNumber - 1])
+ {
+ ScanKeyData *gt,
+ *ge;
+
+ gt = &xform[BTGreaterStrategyNumber - 1];
+ ge = &xform[BTGreaterEqualStrategyNumber - 1];
+
+ /* see note above on function cache */
+ test = (long) fmgr(ge->sk_procedure, gt->sk_argument, ge->sk_argument);
+ if (test)
+ init[BTGreaterEqualStrategyNumber - 1] = 0;
+ else
+ init[BTGreaterStrategyNumber - 1] = 0;
+ }
+
+ /* okay, reorder and count */
+ for (j = BTMaxStrategyNumber; --j >= 0;)
+ if (init[j])
+ key[new_numberOfKeys++] = xform[j];
+
+ if (attno == 1)
+ so->numberOfFirstKeys = new_numberOfKeys;
+
+ if (i == numberOfKeys)
+ break;
+
+ /* initialization for new attno */
+ attno = cur->sk_attno;
+ memset(xform, 0, nbytes);
+ map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
+ BTMaxStrategyNumber,
+ attno);
+ /* haven't looked at any strategies yet */
+ for (j = 0; j <= BTMaxStrategyNumber; j++)
+ init[j] = 0;
+ }
+
+ for (j = BTMaxStrategyNumber; --j >= 0;)
+ {
+ if (cur->sk_procedure == map->entry[j].sk_procedure)
+ break;
+ }
+
+ /* have we seen one of these before? */
+ if (init[j])
+ {
+ /* yup, use the appropriate value */
+ test =
+ (long) FMGR_PTR2(cur->sk_func, cur->sk_procedure,
+ cur->sk_argument, xform[j].sk_argument);
+ if (test)
+ xform[j].sk_argument = cur->sk_argument;
+ else if (j == (BTEqualStrategyNumber - 1))
+ so->qual_ok = 0;/* key == a && key == b, but a != b */
+ }
+ else
+ {
+ /* nope, use this value */
+ memmove(&xform[j], cur, sizeof(*cur));
+ init[j] = 1;
+ }
+
+ i++;
}
-
- i++;
- }
-
- so->numberOfKeys = new_numberOfKeys;
-
- pfree(xform);
+
+ so->numberOfKeys = new_numberOfKeys;
+
+ pfree(xform);
}
BTItem
_bt_formitem(IndexTuple itup)
{
- int nbytes_btitem;
- BTItem btitem;
- Size tuplen;
- extern Oid newoid();
-
- /* see comments in btbuild
-
- if (itup->t_info & INDEX_NULL_MASK)
- elog(WARN, "btree indices cannot include null keys");
- */
-
- /* make a copy of the index tuple with room for the sequence number */
- tuplen = IndexTupleSize(itup);
- nbytes_btitem = tuplen +
- (sizeof(BTItemData) - sizeof(IndexTupleData));
-
- btitem = (BTItem) palloc(nbytes_btitem);
- memmove((char *) &(btitem->bti_itup), (char *) itup, tuplen);
-
+ int nbytes_btitem;
+ BTItem btitem;
+ Size tuplen;
+ extern Oid newoid();
+
+ /*
+ * see comments in btbuild
+ *
+ * if (itup->t_info & INDEX_NULL_MASK) elog(WARN, "btree indices cannot
+ * include null keys");
+ */
+
+ /* make a copy of the index tuple with room for the sequence number */
+ tuplen = IndexTupleSize(itup);
+ nbytes_btitem = tuplen +
+ (sizeof(BTItemData) - sizeof(IndexTupleData));
+
+ btitem = (BTItem) palloc(nbytes_btitem);
+ memmove((char *) &(btitem->bti_itup), (char *) itup, tuplen);
+
#ifndef BTREE_VERSION_1
- btitem->bti_oid = newoid();
+ btitem->bti_oid = newoid();
#endif
- return (btitem);
+ return (btitem);
}
#ifdef NOT_USED
bool
_bt_checkqual(IndexScanDesc scan, IndexTuple itup)
{
- BTScanOpaque so;
-
- so = (BTScanOpaque) scan->opaque;
- if (so->numberOfKeys > 0)
- return (index_keytest(itup, RelationGetTupleDescriptor(scan->relation),
- so->numberOfKeys, so->keyData));
- else
- return (true);
+ BTScanOpaque so;
+
+ so = (BTScanOpaque) scan->opaque;
+ if (so->numberOfKeys > 0)
+ return (index_keytest(itup, RelationGetTupleDescriptor(scan->relation),
+ so->numberOfKeys, so->keyData));
+ else
+ return (true);
}
+
#endif
#ifdef NOT_USED
bool
_bt_checkforkeys(IndexScanDesc scan, IndexTuple itup, Size keysz)
{
- BTScanOpaque so;
-
- so = (BTScanOpaque) scan->opaque;
- if ( keysz > 0 && so->numberOfKeys >= keysz )
- return (index_keytest(itup, RelationGetTupleDescriptor(scan->relation),
- keysz, so->keyData));
- else
- return (true);
+ BTScanOpaque so;
+
+ so = (BTScanOpaque) scan->opaque;
+ if (keysz > 0 && so->numberOfKeys >= keysz)
+ return (index_keytest(itup, RelationGetTupleDescriptor(scan->relation),
+ keysz, so->keyData));
+ else
+ return (true);
}
+
#endif
bool
-_bt_checkkeys (IndexScanDesc scan, IndexTuple tuple, Size *keysok)
+_bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, Size * keysok)
{
- BTScanOpaque so = (BTScanOpaque) scan->opaque;
- Size keysz = so->numberOfKeys;
- TupleDesc tupdesc;
- ScanKey key;
- Datum datum;
- bool isNull;
- int test;
-
- *keysok = 0;
- if ( keysz == 0 )
- return (true);
-
- key = so->keyData;
- tupdesc = RelationGetTupleDescriptor(scan->relation);
-
- IncrIndexProcessed();
-
- while (keysz > 0)
- {
- datum = index_getattr(tuple,
- key[0].sk_attno,
- tupdesc,
- &isNull);
-
- /* btree doesn't support 'A is null' clauses, yet */
- if ( isNull || key[0].sk_flags & SK_ISNULL )
+ BTScanOpaque so = (BTScanOpaque) scan->opaque;
+ Size keysz = so->numberOfKeys;
+ TupleDesc tupdesc;
+ ScanKey key;
+ Datum datum;
+ bool isNull;
+ int test;
+
+ *keysok = 0;
+ if (keysz == 0)
+ return (true);
+
+ key = so->keyData;
+ tupdesc = RelationGetTupleDescriptor(scan->relation);
+
+ IncrIndexProcessed();
+
+ while (keysz > 0)
{
- return (false);
- }
+ datum = index_getattr(tuple,
+ key[0].sk_attno,
+ tupdesc,
+ &isNull);
- if (key[0].sk_flags & SK_COMMUTE) {
- test = (int) (*(key[0].sk_func))
- (DatumGetPointer(key[0].sk_argument),
- datum);
- } else {
- test = (int) (*(key[0].sk_func))
- (datum,
- DatumGetPointer(key[0].sk_argument));
- }
-
- if (!test == !(key[0].sk_flags & SK_NEGATE)) {
- return (false);
+ /* btree doesn't support 'A is null' clauses, yet */
+ if (isNull || key[0].sk_flags & SK_ISNULL)
+ {
+ return (false);
+ }
+
+ if (key[0].sk_flags & SK_COMMUTE)
+ {
+ test = (int) (*(key[0].sk_func))
+ (DatumGetPointer(key[0].sk_argument),
+ datum);
+ }
+ else
+ {
+ test = (int) (*(key[0].sk_func))
+ (datum,
+ DatumGetPointer(key[0].sk_argument));
+ }
+
+ if (!test == !(key[0].sk_flags & SK_NEGATE))
+ {
+ return (false);
+ }
+
+ keysz -= 1;
+ key++;
+ (*keysok)++;
}
-
- keysz -= 1;
- key++;
- (*keysok)++;
- }
-
- return (true);
+
+ return (true);
}