aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gin/ginutil.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-07-11 21:06:29 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-07-11 21:06:29 +0000
commit27cb66fdfe862f395cefa0d498b681ce142f59d8 (patch)
tree23f3223f8f963c4a5f9eca652b073467d85d5406 /src/backend/access/gin/ginutil.c
parent2d6599f47152fe898569ba07b0a0a79e244bbb99 (diff)
downloadpostgresql-27cb66fdfe862f395cefa0d498b681ce142f59d8.tar.gz
postgresql-27cb66fdfe862f395cefa0d498b681ce142f59d8.zip
Multi-column GIN indexes. Teodor Sigaev
Diffstat (limited to 'src/backend/access/gin/ginutil.c')
-rw-r--r--src/backend/access/gin/ginutil.c161
1 files changed, 124 insertions, 37 deletions
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index 36105e20d2d..86b2650c753 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.15 2008/05/16 16:31:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.16 2008/07/11 21:06:29 tgl Exp $
*-------------------------------------------------------------------------
*/
@@ -16,6 +16,7 @@
#include "access/genam.h"
#include "access/gin.h"
#include "access/reloptions.h"
+#include "catalog/pg_type.h"
#include "storage/bufmgr.h"
#include "storage/freespace.h"
#include "storage/lmgr.h"
@@ -23,40 +24,116 @@
void
initGinState(GinState *state, Relation index)
{
- if (index->rd_att->natts != 1)
- elog(ERROR, "numberOfAttributes %d != 1",
- index->rd_att->natts);
-
- state->tupdesc = index->rd_att;
-
- fmgr_info_copy(&(state->compareFn),
- index_getprocinfo(index, 1, GIN_COMPARE_PROC),
- CurrentMemoryContext);
- fmgr_info_copy(&(state->extractValueFn),
- index_getprocinfo(index, 1, GIN_EXTRACTVALUE_PROC),
- CurrentMemoryContext);
- fmgr_info_copy(&(state->extractQueryFn),
- index_getprocinfo(index, 1, GIN_EXTRACTQUERY_PROC),
- CurrentMemoryContext);
- fmgr_info_copy(&(state->consistentFn),
- index_getprocinfo(index, 1, GIN_CONSISTENT_PROC),
- CurrentMemoryContext);
-
- /*
- * Check opclass capability to do partial match.
- */
- if ( index_getprocid(index, 1, GIN_COMPARE_PARTIAL_PROC) != InvalidOid )
+ int i;
+
+ state->origTupdesc = index->rd_att;
+
+ state->oneCol = (index->rd_att->natts == 1) ? true : false;
+
+ for(i=0;i<index->rd_att->natts;i++)
+ {
+ state->tupdesc[i] = CreateTemplateTupleDesc(2,false);
+
+ TupleDescInitEntry( state->tupdesc[i], (AttrNumber) 1, NULL,
+ INT2OID, -1, 0);
+ TupleDescInitEntry( state->tupdesc[i], (AttrNumber) 2, NULL,
+ index->rd_att->attrs[i]->atttypid,
+ index->rd_att->attrs[i]->atttypmod,
+ index->rd_att->attrs[i]->attndims
+ );
+
+ fmgr_info_copy(&(state->compareFn[i]),
+ index_getprocinfo(index, i+1, GIN_COMPARE_PROC),
+ CurrentMemoryContext);
+ fmgr_info_copy(&(state->extractValueFn[i]),
+ index_getprocinfo(index, i+1, GIN_EXTRACTVALUE_PROC),
+ CurrentMemoryContext);
+ fmgr_info_copy(&(state->extractQueryFn[i]),
+ index_getprocinfo(index, i+1, GIN_EXTRACTQUERY_PROC),
+ CurrentMemoryContext);
+ fmgr_info_copy(&(state->consistentFn[i]),
+ index_getprocinfo(index, i+1, GIN_CONSISTENT_PROC),
+ CurrentMemoryContext);
+
+ /*
+ * Check opclass capability to do partial match.
+ */
+ if ( index_getprocid(index, i+1, GIN_COMPARE_PARTIAL_PROC) != InvalidOid )
+ {
+ fmgr_info_copy(&(state->comparePartialFn[i]),
+ index_getprocinfo(index, i+1, GIN_COMPARE_PARTIAL_PROC),
+ CurrentMemoryContext);
+
+ state->canPartialMatch[i] = true;
+ }
+ else
+ {
+ state->canPartialMatch[i] = false;
+ }
+ }
+}
+
+/*
+ * Extract attribute (column) number of stored entry from GIN tuple
+ */
+OffsetNumber
+gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
+{
+ OffsetNumber colN = FirstOffsetNumber;
+
+ if ( !ginstate->oneCol )
{
- fmgr_info_copy(&(state->comparePartialFn),
- index_getprocinfo(index, 1, GIN_COMPARE_PARTIAL_PROC),
- CurrentMemoryContext);
+ Datum res;
+ bool isnull;
+
+ /*
+ * First attribute is always int16, so we can safely use any
+ * tuple descriptor to obtain first attribute of tuple
+ */
+ res = index_getattr(tuple, FirstOffsetNumber, ginstate->tupdesc[0],
+ &isnull);
+ Assert(!isnull);
- state->canPartialMatch = true;
+ colN = DatumGetUInt16(res);
+ Assert( colN >= FirstOffsetNumber && colN <= ginstate->origTupdesc->natts );
+ }
+
+ return colN;
+}
+
+/*
+ * Extract stored datum from GIN tuple
+ */
+Datum
+gin_index_getattr(GinState *ginstate, IndexTuple tuple)
+{
+ bool isnull;
+ Datum res;
+
+ if ( ginstate->oneCol )
+ {
+ /*
+ * Single column index doesn't store attribute numbers in tuples
+ */
+ res = index_getattr(tuple, FirstOffsetNumber, ginstate->origTupdesc,
+ &isnull);
}
else
{
- state->canPartialMatch = false;
+ /*
+ * Since the datum type depends on which index column it's from,
+ * we must be careful to use the right tuple descriptor here.
+ */
+ OffsetNumber colN = gintuple_get_attrnum(ginstate, tuple);
+
+ res = index_getattr(tuple, OffsetNumberNext(FirstOffsetNumber),
+ ginstate->tupdesc[colN - 1],
+ &isnull);
}
+
+ Assert(!isnull);
+
+ return res;
}
/*
@@ -136,16 +213,26 @@ GinInitBuffer(Buffer b, uint32 f)
}
int
-compareEntries(GinState *ginstate, Datum a, Datum b)
+compareEntries(GinState *ginstate, OffsetNumber attnum, Datum a, Datum b)
{
return DatumGetInt32(
FunctionCall2(
- &ginstate->compareFn,
+ &ginstate->compareFn[attnum-1],
a, b
)
);
}
+int
+compareAttEntries(GinState *ginstate, OffsetNumber attnum_a, Datum a,
+ OffsetNumber attnum_b, Datum b)
+{
+ if ( attnum_a == attnum_b )
+ return compareEntries( ginstate, attnum_a, a, b);
+
+ return ( attnum_a < attnum_b ) ? -1 : 1;
+}
+
typedef struct
{
FmgrInfo *cmpDatumFunc;
@@ -165,13 +252,13 @@ cmpEntries(const Datum *a, const Datum *b, cmpEntriesData *arg)
}
Datum *
-extractEntriesS(GinState *ginstate, Datum value, int32 *nentries,
+extractEntriesS(GinState *ginstate, OffsetNumber attnum, Datum value, int32 *nentries,
bool *needUnique)
{
Datum *entries;
entries = (Datum *) DatumGetPointer(FunctionCall2(
- &ginstate->extractValueFn,
+ &ginstate->extractValueFn[attnum-1],
value,
PointerGetDatum(nentries)
));
@@ -184,7 +271,7 @@ extractEntriesS(GinState *ginstate, Datum value, int32 *nentries,
{
cmpEntriesData arg;
- arg.cmpDatumFunc = &ginstate->compareFn;
+ arg.cmpDatumFunc = &ginstate->compareFn[attnum-1];
arg.needUnique = needUnique;
qsort_arg(entries, *nentries, sizeof(Datum),
(qsort_arg_comparator) cmpEntries, (void *) &arg);
@@ -195,10 +282,10 @@ extractEntriesS(GinState *ginstate, Datum value, int32 *nentries,
Datum *
-extractEntriesSU(GinState *ginstate, Datum value, int32 *nentries)
+extractEntriesSU(GinState *ginstate, OffsetNumber attnum, Datum value, int32 *nentries)
{
bool needUnique;
- Datum *entries = extractEntriesS(ginstate, value, nentries,
+ Datum *entries = extractEntriesS(ginstate, attnum, value, nentries,
&needUnique);
if (needUnique)
@@ -210,7 +297,7 @@ extractEntriesSU(GinState *ginstate, Datum value, int32 *nentries)
while (ptr - entries < *nentries)
{
- if (compareEntries(ginstate, *ptr, *res) != 0)
+ if (compareEntries(ginstate, attnum, *ptr, *res) != 0)
*(++res) = *ptr++;
else
ptr++;