Convert index-related tuple handling routines from char 'n'/' ' to bool
convention for isnull flags. Also, remove the useless InsertIndexResult return struct from index AM aminsert calls --- there is no reason for the caller to know where in the index the tuple was inserted, and we were wasting a palloc cycle per insert to deliver this uninteresting value (plus nontrivial complexity in some AMs). I forced initdb because of the change in the signature of the aminsert routines, even though nothing really looks at those pg_proc entries...
This commit is contained in:
parent
fe7015f5e8
commit
ee4ddac137
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.1 2005/02/13 03:04:15 tgl Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.2 2005/03/21 01:23:55 tgl Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="indexam">
|
<chapter id="indexam">
|
||||||
|
@ -151,16 +151,16 @@ ambuild (Relation heapRelation,
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
InsertIndexResult
|
bool
|
||||||
aminsert (Relation indexRelation,
|
aminsert (Relation indexRelation,
|
||||||
Datum *datums,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
ItemPointer heap_tid,
|
ItemPointer heap_tid,
|
||||||
Relation heapRelation,
|
Relation heapRelation,
|
||||||
bool check_uniqueness);
|
bool check_uniqueness);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
Insert a new tuple into an existing index. The <literal>datums</> and
|
Insert a new tuple into an existing index. The <literal>values</> and
|
||||||
<literal>nulls</> arrays give the key values to be indexed, and
|
<literal>isnull</> arrays give the key values to be indexed, and
|
||||||
<literal>heap_tid</> is the TID to be indexed.
|
<literal>heap_tid</> is the TID to be indexed.
|
||||||
If the access method supports unique indexes (its
|
If the access method supports unique indexes (its
|
||||||
<structname>pg_am</>.<structfield>amcanunique</> flag is true) then
|
<structname>pg_am</>.<structfield>amcanunique</> flag is true) then
|
||||||
|
@ -168,8 +168,9 @@ aminsert (Relation indexRelation,
|
||||||
must verify that there is no conflicting row; this is the only situation in
|
must verify that there is no conflicting row; this is the only situation in
|
||||||
which the access method normally needs the <literal>heapRelation</>
|
which the access method normally needs the <literal>heapRelation</>
|
||||||
parameter. See <xref linkend="index-unique-checks"> for details.
|
parameter. See <xref linkend="index-unique-checks"> for details.
|
||||||
The result is a struct that must be pfree'd by the caller. (The result
|
The result is TRUE if an index entry was inserted, FALSE if not. (A FALSE
|
||||||
struct is really quite useless and should be removed...)
|
result does not denote an error condition, but is used for cases such
|
||||||
|
as an index AM refusing to index a NULL.)
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.98 2005/03/16 21:38:04 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.99 2005/03/21 01:23:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -68,7 +68,7 @@ heap_compute_data_size(TupleDesc tupleDesc,
|
||||||
* OLD API with char 'n'/' ' convention for indicating nulls
|
* OLD API with char 'n'/' ' convention for indicating nulls
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
Size
|
static Size
|
||||||
ComputeDataSize(TupleDesc tupleDesc,
|
ComputeDataSize(TupleDesc tupleDesc,
|
||||||
Datum *values,
|
Datum *values,
|
||||||
char *nulls)
|
char *nulls)
|
||||||
|
@ -193,7 +193,7 @@ heap_fill_tuple(TupleDesc tupleDesc,
|
||||||
* OLD API with char 'n'/' ' convention for indicating nulls
|
* OLD API with char 'n'/' ' convention for indicating nulls
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
DataFill(char *data,
|
DataFill(char *data,
|
||||||
TupleDesc tupleDesc,
|
TupleDesc tupleDesc,
|
||||||
Datum *values,
|
Datum *values,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.72 2004/12/31 21:59:07 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/access/common/indextuple.c,v 1.73 2005/03/21 01:23:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -28,13 +28,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* index_formtuple
|
* index_form_tuple
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
IndexTuple
|
IndexTuple
|
||||||
index_formtuple(TupleDesc tupleDescriptor,
|
index_form_tuple(TupleDesc tupleDescriptor,
|
||||||
Datum *value,
|
Datum *values,
|
||||||
char *null)
|
bool *isnull)
|
||||||
{
|
{
|
||||||
char *tp; /* tuple pointer */
|
char *tp; /* tuple pointer */
|
||||||
IndexTuple tuple; /* return tuple */
|
IndexTuple tuple; /* return tuple */
|
||||||
|
@ -47,7 +47,7 @@ index_formtuple(TupleDesc tupleDescriptor,
|
||||||
int numberOfAttributes = tupleDescriptor->natts;
|
int numberOfAttributes = tupleDescriptor->natts;
|
||||||
|
|
||||||
#ifdef TOAST_INDEX_HACK
|
#ifdef TOAST_INDEX_HACK
|
||||||
Datum untoasted_value[INDEX_MAX_KEYS];
|
Datum untoasted_values[INDEX_MAX_KEYS];
|
||||||
bool untoasted_free[INDEX_MAX_KEYS];
|
bool untoasted_free[INDEX_MAX_KEYS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -62,22 +62,22 @@ index_formtuple(TupleDesc tupleDescriptor,
|
||||||
{
|
{
|
||||||
Form_pg_attribute att = tupleDescriptor->attrs[i];
|
Form_pg_attribute att = tupleDescriptor->attrs[i];
|
||||||
|
|
||||||
untoasted_value[i] = value[i];
|
untoasted_values[i] = values[i];
|
||||||
untoasted_free[i] = false;
|
untoasted_free[i] = false;
|
||||||
|
|
||||||
/* Do nothing if value is NULL or not of varlena type */
|
/* Do nothing if value is NULL or not of varlena type */
|
||||||
if (null[i] != ' ' || att->attlen != -1)
|
if (isnull[i] || att->attlen != -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If value is stored EXTERNAL, must fetch it so we are not
|
* If value is stored EXTERNAL, must fetch it so we are not
|
||||||
* depending on outside storage. This should be improved someday.
|
* depending on outside storage. This should be improved someday.
|
||||||
*/
|
*/
|
||||||
if (VARATT_IS_EXTERNAL(value[i]))
|
if (VARATT_IS_EXTERNAL(values[i]))
|
||||||
{
|
{
|
||||||
untoasted_value[i] = PointerGetDatum(
|
untoasted_values[i] = PointerGetDatum(
|
||||||
heap_tuple_fetch_attr(
|
heap_tuple_fetch_attr(
|
||||||
(varattrib *) DatumGetPointer(value[i])));
|
(varattrib *) DatumGetPointer(values[i])));
|
||||||
untoasted_free[i] = true;
|
untoasted_free[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,18 +85,18 @@ index_formtuple(TupleDesc tupleDescriptor,
|
||||||
* If value is above size target, and is of a compressible
|
* If value is above size target, and is of a compressible
|
||||||
* datatype, try to compress it in-line.
|
* datatype, try to compress it in-line.
|
||||||
*/
|
*/
|
||||||
if (VARATT_SIZE(untoasted_value[i]) > TOAST_INDEX_TARGET &&
|
if (VARATT_SIZE(untoasted_values[i]) > TOAST_INDEX_TARGET &&
|
||||||
!VARATT_IS_EXTENDED(untoasted_value[i]) &&
|
!VARATT_IS_EXTENDED(untoasted_values[i]) &&
|
||||||
(att->attstorage == 'x' || att->attstorage == 'm'))
|
(att->attstorage == 'x' || att->attstorage == 'm'))
|
||||||
{
|
{
|
||||||
Datum cvalue = toast_compress_datum(untoasted_value[i]);
|
Datum cvalue = toast_compress_datum(untoasted_values[i]);
|
||||||
|
|
||||||
if (DatumGetPointer(cvalue) != NULL)
|
if (DatumGetPointer(cvalue) != NULL)
|
||||||
{
|
{
|
||||||
/* successful compression */
|
/* successful compression */
|
||||||
if (untoasted_free[i])
|
if (untoasted_free[i])
|
||||||
pfree(DatumGetPointer(untoasted_value[i]));
|
pfree(DatumGetPointer(untoasted_values[i]));
|
||||||
untoasted_value[i] = cvalue;
|
untoasted_values[i] = cvalue;
|
||||||
untoasted_free[i] = true;
|
untoasted_free[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ index_formtuple(TupleDesc tupleDescriptor,
|
||||||
|
|
||||||
for (i = 0; i < numberOfAttributes; i++)
|
for (i = 0; i < numberOfAttributes; i++)
|
||||||
{
|
{
|
||||||
if (null[i] != ' ')
|
if (isnull[i])
|
||||||
{
|
{
|
||||||
hasnull = true;
|
hasnull = true;
|
||||||
break;
|
break;
|
||||||
|
@ -117,41 +117,42 @@ index_formtuple(TupleDesc tupleDescriptor,
|
||||||
|
|
||||||
hoff = IndexInfoFindDataOffset(infomask);
|
hoff = IndexInfoFindDataOffset(infomask);
|
||||||
#ifdef TOAST_INDEX_HACK
|
#ifdef TOAST_INDEX_HACK
|
||||||
size = hoff + ComputeDataSize(tupleDescriptor, untoasted_value, null);
|
size = hoff + heap_compute_data_size(tupleDescriptor,
|
||||||
|
untoasted_values, isnull);
|
||||||
#else
|
#else
|
||||||
size = hoff + ComputeDataSize(tupleDescriptor, value, null);
|
size = hoff + heap_compute_data_size(tupleDescriptor,
|
||||||
|
values, isnull);
|
||||||
#endif
|
#endif
|
||||||
size = MAXALIGN(size); /* be conservative */
|
size = MAXALIGN(size); /* be conservative */
|
||||||
|
|
||||||
tp = (char *) palloc0(size);
|
tp = (char *) palloc0(size);
|
||||||
tuple = (IndexTuple) tp;
|
tuple = (IndexTuple) tp;
|
||||||
|
|
||||||
DataFill((char *) tp + hoff,
|
heap_fill_tuple(tupleDescriptor,
|
||||||
tupleDescriptor,
|
|
||||||
#ifdef TOAST_INDEX_HACK
|
#ifdef TOAST_INDEX_HACK
|
||||||
untoasted_value,
|
untoasted_values,
|
||||||
#else
|
#else
|
||||||
value,
|
values,
|
||||||
#endif
|
#endif
|
||||||
null,
|
isnull,
|
||||||
&tupmask,
|
(char *) tp + hoff,
|
||||||
(hasnull ? (bits8 *) tp + sizeof(*tuple) : NULL));
|
&tupmask,
|
||||||
|
(hasnull ? (bits8 *) tp + sizeof(*tuple) : NULL));
|
||||||
|
|
||||||
#ifdef TOAST_INDEX_HACK
|
#ifdef TOAST_INDEX_HACK
|
||||||
for (i = 0; i < numberOfAttributes; i++)
|
for (i = 0; i < numberOfAttributes; i++)
|
||||||
{
|
{
|
||||||
if (untoasted_free[i])
|
if (untoasted_free[i])
|
||||||
pfree(DatumGetPointer(untoasted_value[i]));
|
pfree(DatumGetPointer(untoasted_values[i]));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We do this because DataFill wants to initialize a "tupmask" which
|
* We do this because heap_fill_tuple wants to initialize a "tupmask"
|
||||||
* is used for HeapTuples, but we want an indextuple infomask. The
|
* which is used for HeapTuples, but we want an indextuple infomask.
|
||||||
* only relevant info is the "has variable attributes" field. We have
|
* The only relevant info is the "has variable attributes" field.
|
||||||
* already set the hasnull bit above.
|
* We have already set the hasnull bit above.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tupmask & HEAP_HASVARWIDTH)
|
if (tupmask & HEAP_HASVARWIDTH)
|
||||||
infomask |= INDEX_VAR_MASK;
|
infomask |= INDEX_VAR_MASK;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.112 2004/12/31 21:59:10 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.113 2005/03/21 01:23:56 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -71,18 +71,16 @@ typedef struct
|
||||||
/* non-export function prototypes */
|
/* non-export function prototypes */
|
||||||
static void gistbuildCallback(Relation index,
|
static void gistbuildCallback(Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state);
|
void *state);
|
||||||
static void gistdoinsert(Relation r,
|
static void gistdoinsert(Relation r,
|
||||||
IndexTuple itup,
|
IndexTuple itup,
|
||||||
InsertIndexResult *res,
|
|
||||||
GISTSTATE *GISTstate);
|
GISTSTATE *GISTstate);
|
||||||
static int gistlayerinsert(Relation r, BlockNumber blkno,
|
static int gistlayerinsert(Relation r, BlockNumber blkno,
|
||||||
IndexTuple **itup,
|
IndexTuple **itup,
|
||||||
int *len,
|
int *len,
|
||||||
InsertIndexResult *res,
|
|
||||||
GISTSTATE *giststate);
|
GISTSTATE *giststate);
|
||||||
static OffsetNumber gistwritebuffer(Relation r,
|
static OffsetNumber gistwritebuffer(Relation r,
|
||||||
Page page,
|
Page page,
|
||||||
|
@ -114,8 +112,7 @@ static IndexTuple *gistSplit(Relation r,
|
||||||
Buffer buffer,
|
Buffer buffer,
|
||||||
IndexTuple *itup,
|
IndexTuple *itup,
|
||||||
int *len,
|
int *len,
|
||||||
GISTSTATE *giststate,
|
GISTSTATE *giststate);
|
||||||
InsertIndexResult *res);
|
|
||||||
static void gistnewroot(Relation r,
|
static void gistnewroot(Relation r,
|
||||||
IndexTuple *itup, int len);
|
IndexTuple *itup, int len);
|
||||||
static void GISTInitBuffer(Buffer b, uint32 f);
|
static void GISTInitBuffer(Buffer b, uint32 f);
|
||||||
|
@ -223,8 +220,8 @@ gistbuild(PG_FUNCTION_ARGS)
|
||||||
static void
|
static void
|
||||||
gistbuildCallback(Relation index,
|
gistbuildCallback(Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state)
|
void *state)
|
||||||
{
|
{
|
||||||
|
@ -235,33 +232,33 @@ gistbuildCallback(Relation index,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* GiST cannot index tuples with leading NULLs */
|
/* GiST cannot index tuples with leading NULLs */
|
||||||
if (nulls[0] == 'n')
|
if (isnull[0])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* immediately compress keys to normalize */
|
/* immediately compress keys to normalize */
|
||||||
for (i = 0; i < buildstate->numindexattrs; i++)
|
for (i = 0; i < buildstate->numindexattrs; i++)
|
||||||
{
|
{
|
||||||
if (nulls[i] == 'n')
|
if (isnull[i])
|
||||||
{
|
{
|
||||||
attdata[i] = (Datum) 0;
|
values[i] = (Datum) 0;
|
||||||
compvec[i] = FALSE;
|
compvec[i] = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gistcentryinit(&buildstate->giststate, i, &tmpcentry, attdata[i],
|
gistcentryinit(&buildstate->giststate, i, &tmpcentry, values[i],
|
||||||
NULL, NULL, (OffsetNumber) 0,
|
NULL, NULL, (OffsetNumber) 0,
|
||||||
-1 /* size is currently bogus */ , TRUE, FALSE);
|
-1 /* size is currently bogus */ , TRUE, FALSE);
|
||||||
if (attdata[i] != tmpcentry.key &&
|
if (values[i] != tmpcentry.key &&
|
||||||
!(isAttByVal(&buildstate->giststate, i)))
|
!(isAttByVal(&buildstate->giststate, i)))
|
||||||
compvec[i] = TRUE;
|
compvec[i] = TRUE;
|
||||||
else
|
else
|
||||||
compvec[i] = FALSE;
|
compvec[i] = FALSE;
|
||||||
attdata[i] = tmpcentry.key;
|
values[i] = tmpcentry.key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* form an index tuple and point it at the heap tuple */
|
/* form an index tuple and point it at the heap tuple */
|
||||||
itup = index_formtuple(buildstate->giststate.tupdesc, attdata, nulls);
|
itup = index_form_tuple(buildstate->giststate.tupdesc, values, isnull);
|
||||||
itup->t_tid = htup->t_self;
|
itup->t_tid = htup->t_self;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -271,13 +268,13 @@ gistbuildCallback(Relation index,
|
||||||
* thing to do if you're inserting single tups, but not when you're
|
* thing to do if you're inserting single tups, but not when you're
|
||||||
* initializing the whole index at once.
|
* initializing the whole index at once.
|
||||||
*/
|
*/
|
||||||
gistdoinsert(index, itup, NULL, &buildstate->giststate);
|
gistdoinsert(index, itup, &buildstate->giststate);
|
||||||
|
|
||||||
buildstate->indtuples += 1;
|
buildstate->indtuples += 1;
|
||||||
|
|
||||||
for (i = 0; i < buildstate->numindexattrs; i++)
|
for (i = 0; i < buildstate->numindexattrs; i++)
|
||||||
if (compvec[i])
|
if (compvec[i])
|
||||||
pfree(DatumGetPointer(attdata[i]));
|
pfree(DatumGetPointer(values[i]));
|
||||||
|
|
||||||
pfree(itup);
|
pfree(itup);
|
||||||
}
|
}
|
||||||
|
@ -292,15 +289,14 @@ Datum
|
||||||
gistinsert(PG_FUNCTION_ARGS)
|
gistinsert(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation r = (Relation) PG_GETARG_POINTER(0);
|
Relation r = (Relation) PG_GETARG_POINTER(0);
|
||||||
Datum *datum = (Datum *) PG_GETARG_POINTER(1);
|
Datum *values = (Datum *) PG_GETARG_POINTER(1);
|
||||||
char *nulls = (char *) PG_GETARG_POINTER(2);
|
bool *isnull = (bool *) PG_GETARG_POINTER(2);
|
||||||
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
|
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
Relation heapRel = (Relation) PG_GETARG_POINTER(4);
|
Relation heapRel = (Relation) PG_GETARG_POINTER(4);
|
||||||
bool checkUnique = PG_GETARG_BOOL(5);
|
bool checkUnique = PG_GETARG_BOOL(5);
|
||||||
#endif
|
#endif
|
||||||
InsertIndexResult res;
|
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
GISTSTATE giststate;
|
GISTSTATE giststate;
|
||||||
GISTENTRY tmpentry;
|
GISTENTRY tmpentry;
|
||||||
|
@ -314,47 +310,43 @@ gistinsert(PG_FUNCTION_ARGS)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* GiST cannot index tuples with leading NULLs */
|
/* GiST cannot index tuples with leading NULLs */
|
||||||
if (nulls[0] == 'n')
|
if (isnull[0])
|
||||||
{
|
PG_RETURN_BOOL(false);
|
||||||
res = NULL;
|
|
||||||
PG_RETURN_POINTER(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
initGISTstate(&giststate, r);
|
initGISTstate(&giststate, r);
|
||||||
|
|
||||||
/* immediately compress keys to normalize */
|
/* immediately compress keys to normalize */
|
||||||
for (i = 0; i < r->rd_att->natts; i++)
|
for (i = 0; i < r->rd_att->natts; i++)
|
||||||
{
|
{
|
||||||
if (nulls[i] == 'n')
|
if (isnull[i])
|
||||||
{
|
{
|
||||||
datum[i] = (Datum) 0;
|
values[i] = (Datum) 0;
|
||||||
compvec[i] = FALSE;
|
compvec[i] = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gistcentryinit(&giststate, i, &tmpentry, datum[i],
|
gistcentryinit(&giststate, i, &tmpentry, values[i],
|
||||||
NULL, NULL, (OffsetNumber) 0,
|
NULL, NULL, (OffsetNumber) 0,
|
||||||
-1 /* size is currently bogus */ , TRUE, FALSE);
|
-1 /* size is currently bogus */ , TRUE, FALSE);
|
||||||
if (datum[i] != tmpentry.key && !(isAttByVal(&giststate, i)))
|
if (values[i] != tmpentry.key && !(isAttByVal(&giststate, i)))
|
||||||
compvec[i] = TRUE;
|
compvec[i] = TRUE;
|
||||||
else
|
else
|
||||||
compvec[i] = FALSE;
|
compvec[i] = FALSE;
|
||||||
datum[i] = tmpentry.key;
|
values[i] = tmpentry.key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
itup = index_formtuple(giststate.tupdesc, datum, nulls);
|
itup = index_form_tuple(giststate.tupdesc, values, isnull);
|
||||||
itup->t_tid = *ht_ctid;
|
itup->t_tid = *ht_ctid;
|
||||||
|
|
||||||
res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
|
gistdoinsert(r, itup, &giststate);
|
||||||
gistdoinsert(r, itup, &res, &giststate);
|
|
||||||
|
|
||||||
for (i = 0; i < r->rd_att->natts; i++)
|
for (i = 0; i < r->rd_att->natts; i++)
|
||||||
if (compvec[i] == TRUE)
|
if (compvec[i] == TRUE)
|
||||||
pfree(DatumGetPointer(datum[i]));
|
pfree(DatumGetPointer(values[i]));
|
||||||
pfree(itup);
|
pfree(itup);
|
||||||
freeGISTstate(&giststate);
|
freeGISTstate(&giststate);
|
||||||
|
|
||||||
PG_RETURN_POINTER(res);
|
PG_RETURN_BOOL(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GIST_PAGEADDITEM
|
#ifdef GIST_PAGEADDITEM
|
||||||
|
@ -411,7 +403,6 @@ gistPageAddItem(GISTSTATE *giststate,
|
||||||
static void
|
static void
|
||||||
gistdoinsert(Relation r,
|
gistdoinsert(Relation r,
|
||||||
IndexTuple itup,
|
IndexTuple itup,
|
||||||
InsertIndexResult *res,
|
|
||||||
GISTSTATE *giststate)
|
GISTSTATE *giststate)
|
||||||
{
|
{
|
||||||
IndexTuple *instup;
|
IndexTuple *instup;
|
||||||
|
@ -423,7 +414,7 @@ gistdoinsert(Relation r,
|
||||||
instup[0] = (IndexTuple) palloc(IndexTupleSize(itup));
|
instup[0] = (IndexTuple) palloc(IndexTupleSize(itup));
|
||||||
memcpy(instup[0], itup, IndexTupleSize(itup));
|
memcpy(instup[0], itup, IndexTupleSize(itup));
|
||||||
|
|
||||||
ret = gistlayerinsert(r, GISTP_ROOT, &instup, &len, res, giststate);
|
ret = gistlayerinsert(r, GISTP_ROOT, &instup, &len, giststate);
|
||||||
if (ret & SPLITED)
|
if (ret & SPLITED)
|
||||||
gistnewroot(r, instup, len);
|
gistnewroot(r, instup, len);
|
||||||
|
|
||||||
|
@ -436,7 +427,6 @@ static int
|
||||||
gistlayerinsert(Relation r, BlockNumber blkno,
|
gistlayerinsert(Relation r, BlockNumber blkno,
|
||||||
IndexTuple **itup, /* in - out, has compressed entry */
|
IndexTuple **itup, /* in - out, has compressed entry */
|
||||||
int *len, /* in - out */
|
int *len, /* in - out */
|
||||||
InsertIndexResult *res, /* out */
|
|
||||||
GISTSTATE *giststate)
|
GISTSTATE *giststate)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
|
@ -468,7 +458,7 @@ gistlayerinsert(Relation r, BlockNumber blkno,
|
||||||
* contains keys for each page 2. if child page wasn't splited,
|
* contains keys for each page 2. if child page wasn't splited,
|
||||||
* then itup contains additional for adjustment of current key
|
* then itup contains additional for adjustment of current key
|
||||||
*/
|
*/
|
||||||
ret = gistlayerinsert(r, nblkno, itup, len, res, giststate);
|
ret = gistlayerinsert(r, nblkno, itup, len, giststate);
|
||||||
|
|
||||||
/* nothing inserted in child */
|
/* nothing inserted in child */
|
||||||
if (!(ret & INSERTED))
|
if (!(ret & INSERTED))
|
||||||
|
@ -520,9 +510,7 @@ gistlayerinsert(Relation r, BlockNumber blkno,
|
||||||
itvec = gistreadbuffer(buffer, &tlen);
|
itvec = gistreadbuffer(buffer, &tlen);
|
||||||
itvec = gistjoinvector(itvec, &tlen, (*itup), *len);
|
itvec = gistjoinvector(itvec, &tlen, (*itup), *len);
|
||||||
oldlen = *len;
|
oldlen = *len;
|
||||||
newitup = gistSplit(r, buffer, itvec, &tlen, giststate,
|
newitup = gistSplit(r, buffer, itvec, &tlen, giststate);
|
||||||
(opaque->flags & F_LEAF) ? res : NULL); /* res only for
|
|
||||||
* inserting in leaf */
|
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
do
|
do
|
||||||
pfree((*itup)[oldlen - 1]);
|
pfree((*itup)[oldlen - 1]);
|
||||||
|
@ -545,12 +533,6 @@ gistlayerinsert(Relation r, BlockNumber blkno,
|
||||||
l = gistwritebuffer(r, page, (*itup), *len, off);
|
l = gistwritebuffer(r, page, (*itup), *len, off);
|
||||||
WriteBuffer(buffer);
|
WriteBuffer(buffer);
|
||||||
|
|
||||||
/*
|
|
||||||
* set res if insert into leaf page, in this case, len = 1 always
|
|
||||||
*/
|
|
||||||
if (res && (opaque->flags & F_LEAF))
|
|
||||||
ItemPointerSet(&((*res)->pointerData), blkno, l);
|
|
||||||
|
|
||||||
if (*len > 1)
|
if (*len > 1)
|
||||||
{ /* previous insert ret & SPLITED != 0 */
|
{ /* previous insert ret & SPLITED != 0 */
|
||||||
int i;
|
int i;
|
||||||
|
@ -666,7 +648,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
|
||||||
{
|
{
|
||||||
Datum attr[INDEX_MAX_KEYS];
|
Datum attr[INDEX_MAX_KEYS];
|
||||||
bool whatfree[INDEX_MAX_KEYS];
|
bool whatfree[INDEX_MAX_KEYS];
|
||||||
char isnull[INDEX_MAX_KEYS];
|
bool isnull[INDEX_MAX_KEYS];
|
||||||
GistEntryVector *evec;
|
GistEntryVector *evec;
|
||||||
Datum datum;
|
Datum datum;
|
||||||
int datumsize,
|
int datumsize,
|
||||||
|
@ -706,7 +688,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
|
||||||
if (reallen == 0)
|
if (reallen == 0)
|
||||||
{
|
{
|
||||||
attr[j] = (Datum) 0;
|
attr[j] = (Datum) 0;
|
||||||
isnull[j] = 'n';
|
isnull[j] = TRUE;
|
||||||
whatfree[j] = FALSE;
|
whatfree[j] = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -732,7 +714,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
|
||||||
gistcentryinit(giststate, j, ¢ry[j], datum,
|
gistcentryinit(giststate, j, ¢ry[j], datum,
|
||||||
NULL, NULL, (OffsetNumber) 0,
|
NULL, NULL, (OffsetNumber) 0,
|
||||||
datumsize, FALSE, FALSE);
|
datumsize, FALSE, FALSE);
|
||||||
isnull[j] = ' ';
|
isnull[j] = FALSE;
|
||||||
attr[j] = centry[j].key;
|
attr[j] = centry[j].key;
|
||||||
if (!isAttByVal(giststate, j))
|
if (!isAttByVal(giststate, j))
|
||||||
{
|
{
|
||||||
|
@ -748,7 +730,7 @@ gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
|
||||||
pfree(evec);
|
pfree(evec);
|
||||||
pfree(needfree);
|
pfree(needfree);
|
||||||
|
|
||||||
newtup = (IndexTuple) index_formtuple(giststate->tupdesc, attr, isnull);
|
newtup = index_form_tuple(giststate->tupdesc, attr, isnull);
|
||||||
for (j = 0; j < r->rd_att->natts; j++)
|
for (j = 0; j < r->rd_att->natts; j++)
|
||||||
if (whatfree[j])
|
if (whatfree[j])
|
||||||
pfree(DatumGetPointer(attr[j]));
|
pfree(DatumGetPointer(attr[j]));
|
||||||
|
@ -768,7 +750,7 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
|
||||||
int datumsize;
|
int datumsize;
|
||||||
bool result,
|
bool result,
|
||||||
neednew = false;
|
neednew = false;
|
||||||
char isnull[INDEX_MAX_KEYS],
|
bool isnull[INDEX_MAX_KEYS],
|
||||||
whatfree[INDEX_MAX_KEYS];
|
whatfree[INDEX_MAX_KEYS];
|
||||||
Datum attr[INDEX_MAX_KEYS];
|
Datum attr[INDEX_MAX_KEYS];
|
||||||
GISTENTRY centry[INDEX_MAX_KEYS],
|
GISTENTRY centry[INDEX_MAX_KEYS],
|
||||||
|
@ -799,8 +781,8 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
|
||||||
{
|
{
|
||||||
if (oldisnull[j] && addisnull[j])
|
if (oldisnull[j] && addisnull[j])
|
||||||
{
|
{
|
||||||
isnull[j] = 'n';
|
|
||||||
attr[j] = (Datum) 0;
|
attr[j] = (Datum) 0;
|
||||||
|
isnull[j] = TRUE;
|
||||||
whatfree[j] = FALSE;
|
whatfree[j] = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -839,8 +821,8 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
|
||||||
NULL, NULL, (OffsetNumber) 0,
|
NULL, NULL, (OffsetNumber) 0,
|
||||||
datumsize, FALSE, FALSE);
|
datumsize, FALSE, FALSE);
|
||||||
|
|
||||||
isnull[j] = ' ';
|
|
||||||
attr[j] = centry[j].key;
|
attr[j] = centry[j].key;
|
||||||
|
isnull[j] = FALSE;
|
||||||
if ((!isAttByVal(giststate, j)))
|
if ((!isAttByVal(giststate, j)))
|
||||||
{
|
{
|
||||||
whatfree[j] = TRUE;
|
whatfree[j] = TRUE;
|
||||||
|
@ -856,7 +838,7 @@ gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *gis
|
||||||
if (neednew)
|
if (neednew)
|
||||||
{
|
{
|
||||||
/* need to update key */
|
/* need to update key */
|
||||||
newtup = (IndexTuple) index_formtuple(giststate->tupdesc, attr, isnull);
|
newtup = index_form_tuple(giststate->tupdesc, attr, isnull);
|
||||||
newtup->t_tid = oldtup->t_tid;
|
newtup->t_tid = oldtup->t_tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,7 +992,7 @@ gistfindgroup(GISTSTATE *giststate, GISTENTRY *valvec, GIST_SPLITVEC *spl)
|
||||||
/* find all other equal value in left part */
|
/* find all other equal value in left part */
|
||||||
if (len)
|
if (len)
|
||||||
{
|
{
|
||||||
/* add current val to list of equial values */
|
/* add current val to list of equal values */
|
||||||
spl->spl_idgrp[spl->spl_left[i]] = curid;
|
spl->spl_idgrp[spl->spl_left[i]] = curid;
|
||||||
/* searching .. */
|
/* searching .. */
|
||||||
for (j = i + 1; j < spl->spl_nleft; j++)
|
for (j = i + 1; j < spl->spl_nleft; j++)
|
||||||
|
@ -1207,8 +1189,7 @@ gistSplit(Relation r,
|
||||||
Buffer buffer,
|
Buffer buffer,
|
||||||
IndexTuple *itup, /* contains compressed entry */
|
IndexTuple *itup, /* contains compressed entry */
|
||||||
int *len,
|
int *len,
|
||||||
GISTSTATE *giststate,
|
GISTSTATE *giststate)
|
||||||
InsertIndexResult *res)
|
|
||||||
{
|
{
|
||||||
Page p;
|
Page p;
|
||||||
Buffer leftbuf,
|
Buffer leftbuf,
|
||||||
|
@ -1344,8 +1325,7 @@ gistSplit(Relation r,
|
||||||
if (gistnospace(right, rvectup, v.spl_nright))
|
if (gistnospace(right, rvectup, v.spl_nright))
|
||||||
{
|
{
|
||||||
nlen = v.spl_nright;
|
nlen = v.spl_nright;
|
||||||
newtup = gistSplit(r, rightbuf, rvectup, &nlen, giststate,
|
newtup = gistSplit(r, rightbuf, rvectup, &nlen, giststate);
|
||||||
(res && rvectup[nlen - 1] == itup[*len - 1]) ? res : NULL);
|
|
||||||
ReleaseBuffer(rightbuf);
|
ReleaseBuffer(rightbuf);
|
||||||
for (j = 1; j < r->rd_att->natts; j++)
|
for (j = 1; j < r->rd_att->natts; j++)
|
||||||
if ((!isAttByVal(giststate, j)) && !v.spl_risnull[j])
|
if ((!isAttByVal(giststate, j)) && !v.spl_risnull[j])
|
||||||
|
@ -1358,9 +1338,6 @@ gistSplit(Relation r,
|
||||||
l = gistwritebuffer(r, right, rvectup, v.spl_nright, FirstOffsetNumber);
|
l = gistwritebuffer(r, right, rvectup, v.spl_nright, FirstOffsetNumber);
|
||||||
WriteBuffer(rightbuf);
|
WriteBuffer(rightbuf);
|
||||||
|
|
||||||
if (res)
|
|
||||||
ItemPointerSet(&((*res)->pointerData), rbknum, l);
|
|
||||||
|
|
||||||
nlen = 1;
|
nlen = 1;
|
||||||
newtup = (IndexTuple *) palloc(sizeof(IndexTuple) * 1);
|
newtup = (IndexTuple *) palloc(sizeof(IndexTuple) * 1);
|
||||||
newtup[0] = gistFormTuple(giststate, r, v.spl_rattr, v.spl_rattrsize, v.spl_risnull);
|
newtup[0] = gistFormTuple(giststate, r, v.spl_rattr, v.spl_rattrsize, v.spl_risnull);
|
||||||
|
@ -1373,8 +1350,7 @@ gistSplit(Relation r,
|
||||||
int llen = v.spl_nleft;
|
int llen = v.spl_nleft;
|
||||||
IndexTuple *lntup;
|
IndexTuple *lntup;
|
||||||
|
|
||||||
lntup = gistSplit(r, leftbuf, lvectup, &llen, giststate,
|
lntup = gistSplit(r, leftbuf, lvectup, &llen, giststate);
|
||||||
(res && lvectup[llen - 1] == itup[*len - 1]) ? res : NULL);
|
|
||||||
ReleaseBuffer(leftbuf);
|
ReleaseBuffer(leftbuf);
|
||||||
|
|
||||||
for (j = 1; j < r->rd_att->natts; j++)
|
for (j = 1; j < r->rd_att->natts; j++)
|
||||||
|
@ -1394,9 +1370,6 @@ gistSplit(Relation r,
|
||||||
|
|
||||||
WriteBuffer(leftbuf);
|
WriteBuffer(leftbuf);
|
||||||
|
|
||||||
if (res)
|
|
||||||
ItemPointerSet(&((*res)->pointerData), lbknum, l);
|
|
||||||
|
|
||||||
nlen += 1;
|
nlen += 1;
|
||||||
newtup = (IndexTuple *) repalloc((void *) newtup, sizeof(IndexTuple) * nlen);
|
newtup = (IndexTuple *) repalloc((void *) newtup, sizeof(IndexTuple) * nlen);
|
||||||
newtup[nlen - 1] = gistFormTuple(giststate, r, v.spl_lattr, v.spl_lattrsize, v.spl_lisnull);
|
newtup[nlen - 1] = gistFormTuple(giststate, r, v.spl_lattr, v.spl_lattrsize, v.spl_lisnull);
|
||||||
|
@ -1704,7 +1677,7 @@ gist_tuple_replacekey(Relation r, GISTENTRY entry, IndexTuple t)
|
||||||
/*
|
/*
|
||||||
* If new entry fits in index tuple, copy it in. To avoid worrying
|
* If new entry fits in index tuple, copy it in. To avoid worrying
|
||||||
* about null-value bitmask, pass it off to the general
|
* about null-value bitmask, pass it off to the general
|
||||||
* index_formtuple routine if either the previous or new value is
|
* index_form_tuple routine if either the previous or new value is
|
||||||
* NULL.
|
* NULL.
|
||||||
*/
|
*/
|
||||||
if (!IsNull && DatumGetPointer(entry.key) != NULL &&
|
if (!IsNull && DatumGetPointer(entry.key) != NULL &&
|
||||||
|
@ -1725,12 +1698,10 @@ gist_tuple_replacekey(Relation r, GISTENTRY entry, IndexTuple t)
|
||||||
/* generate a new index tuple for the compressed entry */
|
/* generate a new index tuple for the compressed entry */
|
||||||
TupleDesc tupDesc = r->rd_att;
|
TupleDesc tupDesc = r->rd_att;
|
||||||
IndexTuple newtup;
|
IndexTuple newtup;
|
||||||
char isnull;
|
bool isnull;
|
||||||
|
|
||||||
isnull = DatumGetPointer(entry.key) != NULL ? ' ' : 'n';
|
isnull = (DatumGetPointer(entry.key) == NULL);
|
||||||
newtup = (IndexTuple) index_formtuple(tupDesc,
|
newtup = index_form_tuple(tupDesc, &(entry.key), &isnull);
|
||||||
&(entry.key),
|
|
||||||
&isnull);
|
|
||||||
newtup->t_tid = t->t_tid;
|
newtup->t_tid = t->t_tid;
|
||||||
return newtup;
|
return newtup;
|
||||||
}
|
}
|
||||||
|
@ -1799,7 +1770,6 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
|
||||||
Datum attdata[], int datumsize[], bool isnull[])
|
Datum attdata[], int datumsize[], bool isnull[])
|
||||||
{
|
{
|
||||||
IndexTuple tup;
|
IndexTuple tup;
|
||||||
char isnullchar[INDEX_MAX_KEYS];
|
|
||||||
bool whatfree[INDEX_MAX_KEYS];
|
bool whatfree[INDEX_MAX_KEYS];
|
||||||
GISTENTRY centry[INDEX_MAX_KEYS];
|
GISTENTRY centry[INDEX_MAX_KEYS];
|
||||||
Datum compatt[INDEX_MAX_KEYS];
|
Datum compatt[INDEX_MAX_KEYS];
|
||||||
|
@ -1809,7 +1779,6 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
|
||||||
{
|
{
|
||||||
if (isnull[j])
|
if (isnull[j])
|
||||||
{
|
{
|
||||||
isnullchar[j] = 'n';
|
|
||||||
compatt[j] = (Datum) 0;
|
compatt[j] = (Datum) 0;
|
||||||
whatfree[j] = FALSE;
|
whatfree[j] = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1818,7 +1787,6 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
|
||||||
gistcentryinit(giststate, j, ¢ry[j], attdata[j],
|
gistcentryinit(giststate, j, ¢ry[j], attdata[j],
|
||||||
NULL, NULL, (OffsetNumber) 0,
|
NULL, NULL, (OffsetNumber) 0,
|
||||||
datumsize[j], FALSE, FALSE);
|
datumsize[j], FALSE, FALSE);
|
||||||
isnullchar[j] = ' ';
|
|
||||||
compatt[j] = centry[j].key;
|
compatt[j] = centry[j].key;
|
||||||
if (!isAttByVal(giststate, j))
|
if (!isAttByVal(giststate, j))
|
||||||
{
|
{
|
||||||
|
@ -1831,7 +1799,7 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tup = (IndexTuple) index_formtuple(giststate->tupdesc, compatt, isnullchar);
|
tup = index_form_tuple(giststate->tupdesc, compatt, isnull);
|
||||||
for (j = 0; j < r->rd_att->natts; j++)
|
for (j = 0; j < r->rd_att->natts; j++)
|
||||||
if (whatfree[j])
|
if (whatfree[j])
|
||||||
pfree(DatumGetPointer(compatt[j]));
|
pfree(DatumGetPointer(compatt[j]));
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.76 2004/12/31 21:59:13 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.77 2005/03/21 01:23:57 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* This file contains only the public interface routines.
|
* This file contains only the public interface routines.
|
||||||
|
@ -36,8 +36,8 @@ typedef struct
|
||||||
|
|
||||||
static void hashbuildCallback(Relation index,
|
static void hashbuildCallback(Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state);
|
void *state);
|
||||||
|
|
||||||
|
@ -103,18 +103,17 @@ hashbuild(PG_FUNCTION_ARGS)
|
||||||
static void
|
static void
|
||||||
hashbuildCallback(Relation index,
|
hashbuildCallback(Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state)
|
void *state)
|
||||||
{
|
{
|
||||||
HashBuildState *buildstate = (HashBuildState *) state;
|
HashBuildState *buildstate = (HashBuildState *) state;
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
HashItem hitem;
|
HashItem hitem;
|
||||||
InsertIndexResult res;
|
|
||||||
|
|
||||||
/* form an index tuple and point it at the heap tuple */
|
/* form an index tuple and point it at the heap tuple */
|
||||||
itup = index_formtuple(RelationGetDescr(index), attdata, nulls);
|
itup = index_form_tuple(RelationGetDescr(index), values, isnull);
|
||||||
itup->t_tid = htup->t_self;
|
itup->t_tid = htup->t_self;
|
||||||
|
|
||||||
/* Hash indexes don't index nulls, see notes in hashinsert */
|
/* Hash indexes don't index nulls, see notes in hashinsert */
|
||||||
|
@ -126,10 +125,7 @@ hashbuildCallback(Relation index,
|
||||||
|
|
||||||
hitem = _hash_formitem(itup);
|
hitem = _hash_formitem(itup);
|
||||||
|
|
||||||
res = _hash_doinsert(index, hitem);
|
_hash_doinsert(index, hitem);
|
||||||
|
|
||||||
if (res)
|
|
||||||
pfree(res);
|
|
||||||
|
|
||||||
buildstate->indtuples += 1;
|
buildstate->indtuples += 1;
|
||||||
|
|
||||||
|
@ -141,27 +137,25 @@ hashbuildCallback(Relation index,
|
||||||
* hashinsert() -- insert an index tuple into a hash table.
|
* hashinsert() -- insert an index tuple into a hash table.
|
||||||
*
|
*
|
||||||
* Hash on the index tuple's key, find the appropriate location
|
* Hash on the index tuple's key, find the appropriate location
|
||||||
* for the new tuple, put it there, and return an InsertIndexResult
|
* for the new tuple, and put it there.
|
||||||
* to the caller.
|
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
hashinsert(PG_FUNCTION_ARGS)
|
hashinsert(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
||||||
Datum *datum = (Datum *) PG_GETARG_POINTER(1);
|
Datum *values = (Datum *) PG_GETARG_POINTER(1);
|
||||||
char *nulls = (char *) PG_GETARG_POINTER(2);
|
bool *isnull = (bool *) PG_GETARG_POINTER(2);
|
||||||
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
|
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
Relation heapRel = (Relation) PG_GETARG_POINTER(4);
|
Relation heapRel = (Relation) PG_GETARG_POINTER(4);
|
||||||
bool checkUnique = PG_GETARG_BOOL(5);
|
bool checkUnique = PG_GETARG_BOOL(5);
|
||||||
#endif
|
#endif
|
||||||
InsertIndexResult res;
|
|
||||||
HashItem hitem;
|
HashItem hitem;
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
|
|
||||||
/* generate an index tuple */
|
/* generate an index tuple */
|
||||||
itup = index_formtuple(RelationGetDescr(rel), datum, nulls);
|
itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
|
||||||
itup->t_tid = *ht_ctid;
|
itup->t_tid = *ht_ctid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -176,17 +170,17 @@ hashinsert(PG_FUNCTION_ARGS)
|
||||||
if (IndexTupleHasNulls(itup))
|
if (IndexTupleHasNulls(itup))
|
||||||
{
|
{
|
||||||
pfree(itup);
|
pfree(itup);
|
||||||
PG_RETURN_POINTER(NULL);
|
PG_RETURN_BOOL(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
hitem = _hash_formitem(itup);
|
hitem = _hash_formitem(itup);
|
||||||
|
|
||||||
res = _hash_doinsert(rel, hitem);
|
_hash_doinsert(rel, hitem);
|
||||||
|
|
||||||
pfree(hitem);
|
pfree(hitem);
|
||||||
pfree(itup);
|
pfree(itup);
|
||||||
|
|
||||||
PG_RETURN_POINTER(res);
|
PG_RETURN_BOOL(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.35 2004/12/31 21:59:13 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.36 2005/03/21 01:23:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -30,7 +30,7 @@ static OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf,
|
||||||
* and hashinsert. By here, hashitem is completely filled in.
|
* and hashinsert. By here, hashitem is completely filled in.
|
||||||
* The datum to be used as a "key" is in the hashitem.
|
* The datum to be used as a "key" is in the hashitem.
|
||||||
*/
|
*/
|
||||||
InsertIndexResult
|
void
|
||||||
_hash_doinsert(Relation rel, HashItem hitem)
|
_hash_doinsert(Relation rel, HashItem hitem)
|
||||||
{
|
{
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
|
@ -39,7 +39,6 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
BlockNumber itup_blkno;
|
BlockNumber itup_blkno;
|
||||||
OffsetNumber itup_off;
|
OffsetNumber itup_off;
|
||||||
InsertIndexResult res;
|
|
||||||
BlockNumber blkno;
|
BlockNumber blkno;
|
||||||
Page page;
|
Page page;
|
||||||
HashPageOpaque pageopaque;
|
HashPageOpaque pageopaque;
|
||||||
|
@ -190,13 +189,6 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
||||||
|
|
||||||
/* Finally drop our pin on the metapage */
|
/* Finally drop our pin on the metapage */
|
||||||
_hash_dropbuf(rel, metabuf);
|
_hash_dropbuf(rel, metabuf);
|
||||||
|
|
||||||
/* Create the return data structure */
|
|
||||||
res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
|
|
||||||
|
|
||||||
ItemPointerSet(&(res->pointerData), itup_blkno, itup_off);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.48 2005/03/14 04:41:12 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.49 2005/03/21 01:23:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
|
@ -283,7 +283,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
|
||||||
int numAttrs;
|
int numAttrs;
|
||||||
int i;
|
int i;
|
||||||
Datum toast_values[MaxHeapAttributeNumber];
|
Datum toast_values[MaxHeapAttributeNumber];
|
||||||
char toast_nulls[MaxHeapAttributeNumber];
|
bool toast_isnull[MaxHeapAttributeNumber];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the tuple descriptor and break down the tuple into fields.
|
* Get the tuple descriptor and break down the tuple into fields.
|
||||||
|
@ -301,7 +301,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
|
||||||
numAttrs = tupleDesc->natts;
|
numAttrs = tupleDesc->natts;
|
||||||
|
|
||||||
Assert(numAttrs <= MaxHeapAttributeNumber);
|
Assert(numAttrs <= MaxHeapAttributeNumber);
|
||||||
heap_deformtuple(oldtup, tupleDesc, toast_values, toast_nulls);
|
heap_deform_tuple(oldtup, tupleDesc, toast_values, toast_isnull);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for external stored attributes and delete them from the
|
* Check for external stored attributes and delete them from the
|
||||||
|
@ -313,7 +313,7 @@ toast_delete(Relation rel, HeapTuple oldtup)
|
||||||
{
|
{
|
||||||
Datum value = toast_values[i];
|
Datum value = toast_values[i];
|
||||||
|
|
||||||
if (toast_nulls[i] != 'n' && VARATT_IS_EXTERNAL(value))
|
if (!toast_isnull[i] && VARATT_IS_EXTERNAL(value))
|
||||||
toast_delete_datum(rel, value);
|
toast_delete_datum(rel, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,8 +343,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
Size maxDataLen;
|
Size maxDataLen;
|
||||||
|
|
||||||
char toast_action[MaxHeapAttributeNumber];
|
char toast_action[MaxHeapAttributeNumber];
|
||||||
char toast_nulls[MaxHeapAttributeNumber];
|
bool toast_isnull[MaxHeapAttributeNumber];
|
||||||
char toast_oldnulls[MaxHeapAttributeNumber];
|
bool toast_oldisnull[MaxHeapAttributeNumber];
|
||||||
Datum toast_values[MaxHeapAttributeNumber];
|
Datum toast_values[MaxHeapAttributeNumber];
|
||||||
Datum toast_oldvalues[MaxHeapAttributeNumber];
|
Datum toast_oldvalues[MaxHeapAttributeNumber];
|
||||||
int32 toast_sizes[MaxHeapAttributeNumber];
|
int32 toast_sizes[MaxHeapAttributeNumber];
|
||||||
|
@ -359,9 +359,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
numAttrs = tupleDesc->natts;
|
numAttrs = tupleDesc->natts;
|
||||||
|
|
||||||
Assert(numAttrs <= MaxHeapAttributeNumber);
|
Assert(numAttrs <= MaxHeapAttributeNumber);
|
||||||
heap_deformtuple(newtup, tupleDesc, toast_values, toast_nulls);
|
heap_deform_tuple(newtup, tupleDesc, toast_values, toast_isnull);
|
||||||
if (oldtup != NULL)
|
if (oldtup != NULL)
|
||||||
heap_deformtuple(oldtup, tupleDesc, toast_oldvalues, toast_oldnulls);
|
heap_deform_tuple(oldtup, tupleDesc, toast_oldvalues, toast_oldisnull);
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Then collect information about the values given
|
* Then collect information about the values given
|
||||||
|
@ -396,10 +396,10 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
* If the old value is an external stored one, check if it has
|
* If the old value is an external stored one, check if it has
|
||||||
* changed so we have to delete it later.
|
* changed so we have to delete it later.
|
||||||
*/
|
*/
|
||||||
if (att[i]->attlen == -1 && toast_oldnulls[i] != 'n' &&
|
if (att[i]->attlen == -1 && !toast_oldisnull[i] &&
|
||||||
VARATT_IS_EXTERNAL(old_value))
|
VARATT_IS_EXTERNAL(old_value))
|
||||||
{
|
{
|
||||||
if (toast_nulls[i] == 'n' || !VARATT_IS_EXTERNAL(new_value) ||
|
if (toast_isnull[i] || !VARATT_IS_EXTERNAL(new_value) ||
|
||||||
old_value->va_content.va_external.va_valueid !=
|
old_value->va_content.va_external.va_valueid !=
|
||||||
new_value->va_content.va_external.va_valueid ||
|
new_value->va_content.va_external.va_valueid ||
|
||||||
old_value->va_content.va_external.va_toastrelid !=
|
old_value->va_content.va_external.va_toastrelid !=
|
||||||
|
@ -436,7 +436,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
/*
|
/*
|
||||||
* Handle NULL attributes
|
* Handle NULL attributes
|
||||||
*/
|
*/
|
||||||
if (toast_nulls[i] == 'n')
|
if (toast_isnull[i])
|
||||||
{
|
{
|
||||||
toast_action[i] = 'p';
|
toast_action[i] = 'p';
|
||||||
has_nulls = true;
|
has_nulls = true;
|
||||||
|
@ -499,7 +499,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
/*
|
/*
|
||||||
* Look for attributes with attstorage 'x' to compress
|
* Look for attributes with attstorage 'x' to compress
|
||||||
*/
|
*/
|
||||||
while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
|
while (MAXALIGN(heap_compute_data_size(tupleDesc,
|
||||||
|
toast_values, toast_isnull)) >
|
||||||
maxDataLen)
|
maxDataLen)
|
||||||
{
|
{
|
||||||
int biggest_attno = -1;
|
int biggest_attno = -1;
|
||||||
|
@ -560,7 +561,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
* Second we look for attributes of attstorage 'x' or 'e' that are
|
* Second we look for attributes of attstorage 'x' or 'e' that are
|
||||||
* still inline.
|
* still inline.
|
||||||
*/
|
*/
|
||||||
while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
|
while (MAXALIGN(heap_compute_data_size(tupleDesc,
|
||||||
|
toast_values, toast_isnull)) >
|
||||||
maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
|
maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
|
||||||
{
|
{
|
||||||
int biggest_attno = -1;
|
int biggest_attno = -1;
|
||||||
|
@ -611,7 +613,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
* Round 3 - this time we take attributes with storage 'm' into
|
* Round 3 - this time we take attributes with storage 'm' into
|
||||||
* compression
|
* compression
|
||||||
*/
|
*/
|
||||||
while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
|
while (MAXALIGN(heap_compute_data_size(tupleDesc,
|
||||||
|
toast_values, toast_isnull)) >
|
||||||
maxDataLen)
|
maxDataLen)
|
||||||
{
|
{
|
||||||
int biggest_attno = -1;
|
int biggest_attno = -1;
|
||||||
|
@ -671,7 +674,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
/*
|
/*
|
||||||
* Finally we store attributes of type 'm' external
|
* Finally we store attributes of type 'm' external
|
||||||
*/
|
*/
|
||||||
while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) >
|
while (MAXALIGN(heap_compute_data_size(tupleDesc,
|
||||||
|
toast_values, toast_isnull)) >
|
||||||
maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
|
maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
|
||||||
{
|
{
|
||||||
int biggest_attno = -1;
|
int biggest_attno = -1;
|
||||||
|
@ -739,7 +743,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
new_len += sizeof(Oid);
|
new_len += sizeof(Oid);
|
||||||
new_len = MAXALIGN(new_len);
|
new_len = MAXALIGN(new_len);
|
||||||
Assert(new_len == olddata->t_hoff);
|
Assert(new_len == olddata->t_hoff);
|
||||||
new_len += ComputeDataSize(tupleDesc, toast_values, toast_nulls);
|
new_len += heap_compute_data_size(tupleDesc,
|
||||||
|
toast_values, toast_isnull);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate new tuple in same context as old one.
|
* Allocate new tuple in same context as old one.
|
||||||
|
@ -753,12 +758,12 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||||
*/
|
*/
|
||||||
memcpy(new_data, olddata, olddata->t_hoff);
|
memcpy(new_data, olddata, olddata->t_hoff);
|
||||||
|
|
||||||
DataFill((char *) new_data + olddata->t_hoff,
|
heap_fill_tuple(tupleDesc,
|
||||||
tupleDesc,
|
toast_values,
|
||||||
toast_values,
|
toast_isnull,
|
||||||
toast_nulls,
|
(char *) new_data + olddata->t_hoff,
|
||||||
&(newtup->t_data->t_infomask),
|
&(newtup->t_data->t_infomask),
|
||||||
has_nulls ? newtup->t_data->t_bits : NULL);
|
has_nulls ? newtup->t_data->t_bits : NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In the case we modified a previously modified tuple again, free
|
* In the case we modified a previously modified tuple again, free
|
||||||
|
@ -810,7 +815,7 @@ toast_flatten_tuple_attribute(Datum value,
|
||||||
bool need_change = false;
|
bool need_change = false;
|
||||||
bool has_nulls = false;
|
bool has_nulls = false;
|
||||||
Datum toast_values[MaxTupleAttributeNumber];
|
Datum toast_values[MaxTupleAttributeNumber];
|
||||||
char toast_nulls[MaxTupleAttributeNumber];
|
bool toast_isnull[MaxTupleAttributeNumber];
|
||||||
bool toast_free[MaxTupleAttributeNumber];
|
bool toast_free[MaxTupleAttributeNumber];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -836,7 +841,7 @@ toast_flatten_tuple_attribute(Datum value,
|
||||||
tmptup.t_data = olddata;
|
tmptup.t_data = olddata;
|
||||||
|
|
||||||
Assert(numAttrs <= MaxTupleAttributeNumber);
|
Assert(numAttrs <= MaxTupleAttributeNumber);
|
||||||
heap_deformtuple(&tmptup, tupleDesc, toast_values, toast_nulls);
|
heap_deform_tuple(&tmptup, tupleDesc, toast_values, toast_isnull);
|
||||||
|
|
||||||
memset(toast_free, 0, numAttrs * sizeof(bool));
|
memset(toast_free, 0, numAttrs * sizeof(bool));
|
||||||
|
|
||||||
|
@ -845,7 +850,7 @@ toast_flatten_tuple_attribute(Datum value,
|
||||||
/*
|
/*
|
||||||
* Look at non-null varlena attributes
|
* Look at non-null varlena attributes
|
||||||
*/
|
*/
|
||||||
if (toast_nulls[i] == 'n')
|
if (toast_isnull[i])
|
||||||
has_nulls = true;
|
has_nulls = true;
|
||||||
else if (att[i]->attlen == -1)
|
else if (att[i]->attlen == -1)
|
||||||
{
|
{
|
||||||
|
@ -879,7 +884,7 @@ toast_flatten_tuple_attribute(Datum value,
|
||||||
new_len += sizeof(Oid);
|
new_len += sizeof(Oid);
|
||||||
new_len = MAXALIGN(new_len);
|
new_len = MAXALIGN(new_len);
|
||||||
Assert(new_len == olddata->t_hoff);
|
Assert(new_len == olddata->t_hoff);
|
||||||
new_len += ComputeDataSize(tupleDesc, toast_values, toast_nulls);
|
new_len += heap_compute_data_size(tupleDesc, toast_values, toast_isnull);
|
||||||
|
|
||||||
new_data = (HeapTupleHeader) palloc0(new_len);
|
new_data = (HeapTupleHeader) palloc0(new_len);
|
||||||
|
|
||||||
|
@ -890,12 +895,12 @@ toast_flatten_tuple_attribute(Datum value,
|
||||||
|
|
||||||
HeapTupleHeaderSetDatumLength(new_data, new_len);
|
HeapTupleHeaderSetDatumLength(new_data, new_len);
|
||||||
|
|
||||||
DataFill((char *) new_data + olddata->t_hoff,
|
heap_fill_tuple(tupleDesc,
|
||||||
tupleDesc,
|
toast_values,
|
||||||
toast_values,
|
toast_isnull,
|
||||||
toast_nulls,
|
(char *) new_data + olddata->t_hoff,
|
||||||
&(new_data->t_infomask),
|
&(new_data->t_infomask),
|
||||||
has_nulls ? new_data->t_bits : NULL);
|
has_nulls ? new_data->t_bits : NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free allocated temp values
|
* Free allocated temp values
|
||||||
|
@ -955,10 +960,9 @@ toast_save_datum(Relation rel, Datum value)
|
||||||
Relation toastrel;
|
Relation toastrel;
|
||||||
Relation toastidx;
|
Relation toastidx;
|
||||||
HeapTuple toasttup;
|
HeapTuple toasttup;
|
||||||
InsertIndexResult idxres;
|
|
||||||
TupleDesc toasttupDesc;
|
TupleDesc toasttupDesc;
|
||||||
Datum t_values[3];
|
Datum t_values[3];
|
||||||
char t_nulls[3];
|
bool t_isnull[3];
|
||||||
varattrib *result;
|
varattrib *result;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -996,9 +1000,9 @@ toast_save_datum(Relation rel, Datum value)
|
||||||
*/
|
*/
|
||||||
t_values[0] = ObjectIdGetDatum(result->va_content.va_external.va_valueid);
|
t_values[0] = ObjectIdGetDatum(result->va_content.va_external.va_valueid);
|
||||||
t_values[2] = PointerGetDatum(&chunk_data);
|
t_values[2] = PointerGetDatum(&chunk_data);
|
||||||
t_nulls[0] = ' ';
|
t_isnull[0] = false;
|
||||||
t_nulls[1] = ' ';
|
t_isnull[1] = false;
|
||||||
t_nulls[2] = ' ';
|
t_isnull[2] = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the data to process
|
* Get the data to process
|
||||||
|
@ -1031,7 +1035,7 @@ toast_save_datum(Relation rel, Datum value)
|
||||||
t_values[1] = Int32GetDatum(chunk_seq++);
|
t_values[1] = Int32GetDatum(chunk_seq++);
|
||||||
VARATT_SIZEP(&chunk_data) = chunk_size + VARHDRSZ;
|
VARATT_SIZEP(&chunk_data) = chunk_size + VARHDRSZ;
|
||||||
memcpy(VARATT_DATA(&chunk_data), data_p, chunk_size);
|
memcpy(VARATT_DATA(&chunk_data), data_p, chunk_size);
|
||||||
toasttup = heap_formtuple(toasttupDesc, t_values, t_nulls);
|
toasttup = heap_form_tuple(toasttupDesc, t_values, t_isnull);
|
||||||
if (!HeapTupleIsValid(toasttup))
|
if (!HeapTupleIsValid(toasttup))
|
||||||
elog(ERROR, "failed to build TOAST tuple");
|
elog(ERROR, "failed to build TOAST tuple");
|
||||||
|
|
||||||
|
@ -1045,16 +1049,13 @@ toast_save_datum(Relation rel, Datum value)
|
||||||
* Note also that there had better not be any user-created index on
|
* Note also that there had better not be any user-created index on
|
||||||
* the TOAST table, since we don't bother to update anything else.
|
* the TOAST table, since we don't bother to update anything else.
|
||||||
*/
|
*/
|
||||||
idxres = index_insert(toastidx, t_values, t_nulls,
|
index_insert(toastidx, t_values, t_isnull,
|
||||||
&(toasttup->t_self),
|
&(toasttup->t_self),
|
||||||
toastrel, toastidx->rd_index->indisunique);
|
toastrel, toastidx->rd_index->indisunique);
|
||||||
if (idxres == NULL)
|
|
||||||
elog(ERROR, "failed to insert index entry for TOAST tuple");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free memory
|
* Free memory
|
||||||
*/
|
*/
|
||||||
pfree(idxres);
|
|
||||||
heap_freetuple(toasttup);
|
heap_freetuple(toasttup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.77 2004/12/31 21:59:19 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.78 2005/03/21 01:23:58 tgl Exp $
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
* index_open - open an index relation by relation OID
|
* index_open - open an index relation by relation OID
|
||||||
|
@ -211,16 +211,15 @@ index_close(Relation relation)
|
||||||
* index_insert - insert an index tuple into a relation
|
* index_insert - insert an index tuple into a relation
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
InsertIndexResult
|
bool
|
||||||
index_insert(Relation indexRelation,
|
index_insert(Relation indexRelation,
|
||||||
Datum *datums,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
ItemPointer heap_t_ctid,
|
ItemPointer heap_t_ctid,
|
||||||
Relation heapRelation,
|
Relation heapRelation,
|
||||||
bool check_uniqueness)
|
bool check_uniqueness)
|
||||||
{
|
{
|
||||||
RegProcedure procedure;
|
RegProcedure procedure;
|
||||||
InsertIndexResult specificResult;
|
|
||||||
|
|
||||||
RELATION_CHECKS;
|
RELATION_CHECKS;
|
||||||
GET_REL_PROCEDURE(insert, aminsert);
|
GET_REL_PROCEDURE(insert, aminsert);
|
||||||
|
@ -228,17 +227,13 @@ index_insert(Relation indexRelation,
|
||||||
/*
|
/*
|
||||||
* have the am's insert proc do all the work.
|
* have the am's insert proc do all the work.
|
||||||
*/
|
*/
|
||||||
specificResult = (InsertIndexResult)
|
return DatumGetBool(OidFunctionCall6(procedure,
|
||||||
DatumGetPointer(OidFunctionCall6(procedure,
|
|
||||||
PointerGetDatum(indexRelation),
|
PointerGetDatum(indexRelation),
|
||||||
PointerGetDatum(datums),
|
PointerGetDatum(values),
|
||||||
PointerGetDatum(nulls),
|
PointerGetDatum(isnull),
|
||||||
PointerGetDatum(heap_t_ctid),
|
PointerGetDatum(heap_t_ctid),
|
||||||
PointerGetDatum(heapRelation),
|
PointerGetDatum(heapRelation),
|
||||||
BoolGetDatum(check_uniqueness)));
|
BoolGetDatum(check_uniqueness)));
|
||||||
|
|
||||||
/* must be pfree'ed */
|
|
||||||
return specificResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.119 2004/12/31 21:59:22 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.120 2005/03/21 01:23:59 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -41,7 +41,7 @@ static Buffer _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
|
||||||
static TransactionId _bt_check_unique(Relation rel, BTItem btitem,
|
static TransactionId _bt_check_unique(Relation rel, BTItem btitem,
|
||||||
Relation heapRel, Buffer buf,
|
Relation heapRel, Buffer buf,
|
||||||
ScanKey itup_scankey);
|
ScanKey itup_scankey);
|
||||||
static InsertIndexResult _bt_insertonpg(Relation rel, Buffer buf,
|
static void _bt_insertonpg(Relation rel, Buffer buf,
|
||||||
BTStack stack,
|
BTStack stack,
|
||||||
int keysz, ScanKey scankey,
|
int keysz, ScanKey scankey,
|
||||||
BTItem btitem,
|
BTItem btitem,
|
||||||
|
@ -71,7 +71,7 @@ static bool _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
|
||||||
* This routine is called by the public interface routines, btbuild
|
* This routine is called by the public interface routines, btbuild
|
||||||
* and btinsert. By here, btitem is filled in, including the TID.
|
* and btinsert. By here, btitem is filled in, including the TID.
|
||||||
*/
|
*/
|
||||||
InsertIndexResult
|
void
|
||||||
_bt_doinsert(Relation rel, BTItem btitem,
|
_bt_doinsert(Relation rel, BTItem btitem,
|
||||||
bool index_is_unique, Relation heapRel)
|
bool index_is_unique, Relation heapRel)
|
||||||
{
|
{
|
||||||
|
@ -80,7 +80,6 @@ _bt_doinsert(Relation rel, BTItem btitem,
|
||||||
ScanKey itup_scankey;
|
ScanKey itup_scankey;
|
||||||
BTStack stack;
|
BTStack stack;
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
InsertIndexResult res;
|
|
||||||
|
|
||||||
/* we need a scan key to do our search, so build one */
|
/* we need a scan key to do our search, so build one */
|
||||||
itup_scankey = _bt_mkscankey(rel, itup);
|
itup_scankey = _bt_mkscankey(rel, itup);
|
||||||
|
@ -138,14 +137,11 @@ top:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do the insertion */
|
/* do the insertion */
|
||||||
res = _bt_insertonpg(rel, buf, stack, natts, itup_scankey, btitem,
|
_bt_insertonpg(rel, buf, stack, natts, itup_scankey, btitem, 0, false);
|
||||||
0, false);
|
|
||||||
|
|
||||||
/* be tidy */
|
/* be tidy */
|
||||||
_bt_freestack(stack);
|
_bt_freestack(stack);
|
||||||
_bt_freeskey(itup_scankey);
|
_bt_freeskey(itup_scankey);
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -357,7 +353,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
|
||||||
* insertion on internal pages.
|
* insertion on internal pages.
|
||||||
*----------
|
*----------
|
||||||
*/
|
*/
|
||||||
static InsertIndexResult
|
static void
|
||||||
_bt_insertonpg(Relation rel,
|
_bt_insertonpg(Relation rel,
|
||||||
Buffer buf,
|
Buffer buf,
|
||||||
BTStack stack,
|
BTStack stack,
|
||||||
|
@ -367,7 +363,6 @@ _bt_insertonpg(Relation rel,
|
||||||
OffsetNumber afteritem,
|
OffsetNumber afteritem,
|
||||||
bool split_only_page)
|
bool split_only_page)
|
||||||
{
|
{
|
||||||
InsertIndexResult res;
|
|
||||||
Page page;
|
Page page;
|
||||||
BTPageOpaque lpageop;
|
BTPageOpaque lpageop;
|
||||||
OffsetNumber itup_off;
|
OffsetNumber itup_off;
|
||||||
|
@ -630,12 +625,6 @@ _bt_insertonpg(Relation rel,
|
||||||
|
|
||||||
_bt_wrtbuf(rel, buf);
|
_bt_wrtbuf(rel, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* by here, the new tuple is inserted at itup_blkno/itup_off */
|
|
||||||
res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
|
|
||||||
ItemPointerSet(&(res->pointerData), itup_blkno, itup_off);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1190,7 +1179,6 @@ _bt_insert_parent(Relation rel,
|
||||||
BlockNumber bknum = BufferGetBlockNumber(buf);
|
BlockNumber bknum = BufferGetBlockNumber(buf);
|
||||||
BlockNumber rbknum = BufferGetBlockNumber(rbuf);
|
BlockNumber rbknum = BufferGetBlockNumber(rbuf);
|
||||||
Page page = BufferGetPage(buf);
|
Page page = BufferGetPage(buf);
|
||||||
InsertIndexResult newres;
|
|
||||||
BTItem new_item;
|
BTItem new_item;
|
||||||
BTStackData fakestack;
|
BTStackData fakestack;
|
||||||
BTItem ritem;
|
BTItem ritem;
|
||||||
|
@ -1244,12 +1232,11 @@ _bt_insert_parent(Relation rel,
|
||||||
RelationGetRelationName(rel));
|
RelationGetRelationName(rel));
|
||||||
|
|
||||||
/* Recursively update the parent */
|
/* Recursively update the parent */
|
||||||
newres = _bt_insertonpg(rel, pbuf, stack->bts_parent,
|
_bt_insertonpg(rel, pbuf, stack->bts_parent,
|
||||||
0, NULL, new_item, stack->bts_offset,
|
0, NULL, new_item, stack->bts_offset,
|
||||||
is_only);
|
is_only);
|
||||||
|
|
||||||
/* be tidy */
|
/* be tidy */
|
||||||
pfree(newres);
|
|
||||||
pfree(new_item);
|
pfree(new_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.125 2005/03/20 22:00:50 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.126 2005/03/21 01:23:59 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -52,8 +52,8 @@ bool FastBuild = true; /* use SORT instead of insertion build */
|
||||||
static void _bt_restscan(IndexScanDesc scan);
|
static void _bt_restscan(IndexScanDesc scan);
|
||||||
static void btbuildCallback(Relation index,
|
static void btbuildCallback(Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state);
|
void *state);
|
||||||
|
|
||||||
|
@ -178,18 +178,17 @@ btbuild(PG_FUNCTION_ARGS)
|
||||||
static void
|
static void
|
||||||
btbuildCallback(Relation index,
|
btbuildCallback(Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state)
|
void *state)
|
||||||
{
|
{
|
||||||
BTBuildState *buildstate = (BTBuildState *) state;
|
BTBuildState *buildstate = (BTBuildState *) state;
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
BTItem btitem;
|
BTItem btitem;
|
||||||
InsertIndexResult res;
|
|
||||||
|
|
||||||
/* form an index tuple and point it at the heap tuple */
|
/* form an index tuple and point it at the heap tuple */
|
||||||
itup = index_formtuple(RelationGetDescr(index), attdata, nulls);
|
itup = index_form_tuple(RelationGetDescr(index), values, isnull);
|
||||||
itup->t_tid = htup->t_self;
|
itup->t_tid = htup->t_self;
|
||||||
|
|
||||||
btitem = _bt_formitem(itup);
|
btitem = _bt_formitem(itup);
|
||||||
|
@ -212,10 +211,8 @@ btbuildCallback(Relation index,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = _bt_doinsert(index, btitem,
|
_bt_doinsert(index, btitem,
|
||||||
buildstate->isUnique, buildstate->heapRel);
|
buildstate->isUnique, buildstate->heapRel);
|
||||||
if (res)
|
|
||||||
pfree(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildstate->indtuples += 1;
|
buildstate->indtuples += 1;
|
||||||
|
@ -228,33 +225,31 @@ btbuildCallback(Relation index,
|
||||||
* btinsert() -- insert an index tuple into a btree.
|
* btinsert() -- insert an index tuple into a btree.
|
||||||
*
|
*
|
||||||
* Descend the tree recursively, find the appropriate location for our
|
* Descend the tree recursively, find the appropriate location for our
|
||||||
* new tuple, put it there, set its unique OID as appropriate, and
|
* new tuple, and put it there.
|
||||||
* return an InsertIndexResult to the caller.
|
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
btinsert(PG_FUNCTION_ARGS)
|
btinsert(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
||||||
Datum *datum = (Datum *) PG_GETARG_POINTER(1);
|
Datum *values = (Datum *) PG_GETARG_POINTER(1);
|
||||||
char *nulls = (char *) PG_GETARG_POINTER(2);
|
bool *isnull = (bool *) PG_GETARG_POINTER(2);
|
||||||
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
|
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
|
||||||
Relation heapRel = (Relation) PG_GETARG_POINTER(4);
|
Relation heapRel = (Relation) PG_GETARG_POINTER(4);
|
||||||
bool checkUnique = PG_GETARG_BOOL(5);
|
bool checkUnique = PG_GETARG_BOOL(5);
|
||||||
InsertIndexResult res;
|
|
||||||
BTItem btitem;
|
BTItem btitem;
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
|
|
||||||
/* generate an index tuple */
|
/* generate an index tuple */
|
||||||
itup = index_formtuple(RelationGetDescr(rel), datum, nulls);
|
itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
|
||||||
itup->t_tid = *ht_ctid;
|
itup->t_tid = *ht_ctid;
|
||||||
btitem = _bt_formitem(itup);
|
btitem = _bt_formitem(itup);
|
||||||
|
|
||||||
res = _bt_doinsert(rel, btitem, checkUnique, heapRel);
|
_bt_doinsert(rel, btitem, checkUnique, heapRel);
|
||||||
|
|
||||||
pfree(btitem);
|
pfree(btitem);
|
||||||
pfree(itup);
|
pfree(itup);
|
||||||
|
|
||||||
PG_RETURN_POINTER(res);
|
PG_RETURN_BOOL(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtree.c,v 1.87 2005/01/24 02:47:26 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/rtree/rtree.c,v 1.88 2005/03/21 01:24:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -81,15 +81,14 @@ typedef struct
|
||||||
/* non-export function prototypes */
|
/* non-export function prototypes */
|
||||||
static void rtbuildCallback(Relation index,
|
static void rtbuildCallback(Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state);
|
void *state);
|
||||||
static InsertIndexResult rtdoinsert(Relation r, IndexTuple itup,
|
static void rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate);
|
||||||
RTSTATE *rtstate);
|
|
||||||
static void rttighten(Relation r, RTSTACK *stk, Datum datum, int att_size,
|
static void rttighten(Relation r, RTSTACK *stk, Datum datum, int att_size,
|
||||||
RTSTATE *rtstate);
|
RTSTATE *rtstate);
|
||||||
static InsertIndexResult rtdosplit(Relation r, Buffer buffer, RTSTACK *stack,
|
static void rtdosplit(Relation r, Buffer buffer, RTSTACK *stack,
|
||||||
IndexTuple itup, RTSTATE *rtstate);
|
IndexTuple itup, RTSTATE *rtstate);
|
||||||
static void rtintinsert(Relation r, RTSTACK *stk, IndexTuple ltup,
|
static void rtintinsert(Relation r, RTSTACK *stk, IndexTuple ltup,
|
||||||
IndexTuple rtup, RTSTATE *rtstate);
|
IndexTuple rtup, RTSTATE *rtstate);
|
||||||
|
@ -174,17 +173,16 @@ rtbuild(PG_FUNCTION_ARGS)
|
||||||
static void
|
static void
|
||||||
rtbuildCallback(Relation index,
|
rtbuildCallback(Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state)
|
void *state)
|
||||||
{
|
{
|
||||||
RTBuildState *buildstate = (RTBuildState *) state;
|
RTBuildState *buildstate = (RTBuildState *) state;
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
InsertIndexResult res;
|
|
||||||
|
|
||||||
/* form an index tuple and point it at the heap tuple */
|
/* form an index tuple and point it at the heap tuple */
|
||||||
itup = index_formtuple(RelationGetDescr(index), attdata, nulls);
|
itup = index_form_tuple(RelationGetDescr(index), values, isnull);
|
||||||
itup->t_tid = htup->t_self;
|
itup->t_tid = htup->t_self;
|
||||||
|
|
||||||
/* rtree indexes don't index nulls, see notes in rtinsert */
|
/* rtree indexes don't index nulls, see notes in rtinsert */
|
||||||
|
@ -201,10 +199,7 @@ rtbuildCallback(Relation index,
|
||||||
* if you're inserting single tups, but not when you're initializing
|
* if you're inserting single tups, but not when you're initializing
|
||||||
* the whole index at once.
|
* the whole index at once.
|
||||||
*/
|
*/
|
||||||
res = rtdoinsert(index, itup, &buildstate->rtState);
|
rtdoinsert(index, itup, &buildstate->rtState);
|
||||||
|
|
||||||
if (res)
|
|
||||||
pfree(res);
|
|
||||||
|
|
||||||
buildstate->indtuples += 1;
|
buildstate->indtuples += 1;
|
||||||
|
|
||||||
|
@ -221,20 +216,19 @@ Datum
|
||||||
rtinsert(PG_FUNCTION_ARGS)
|
rtinsert(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation r = (Relation) PG_GETARG_POINTER(0);
|
Relation r = (Relation) PG_GETARG_POINTER(0);
|
||||||
Datum *datum = (Datum *) PG_GETARG_POINTER(1);
|
Datum *values = (Datum *) PG_GETARG_POINTER(1);
|
||||||
char *nulls = (char *) PG_GETARG_POINTER(2);
|
bool *isnull = (bool *) PG_GETARG_POINTER(2);
|
||||||
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
|
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
Relation heapRel = (Relation) PG_GETARG_POINTER(4);
|
Relation heapRel = (Relation) PG_GETARG_POINTER(4);
|
||||||
bool checkUnique = PG_GETARG_BOOL(5);
|
bool checkUnique = PG_GETARG_BOOL(5);
|
||||||
#endif
|
#endif
|
||||||
InsertIndexResult res;
|
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
RTSTATE rtState;
|
RTSTATE rtState;
|
||||||
|
|
||||||
/* generate an index tuple */
|
/* generate an index tuple */
|
||||||
itup = index_formtuple(RelationGetDescr(r), datum, nulls);
|
itup = index_form_tuple(RelationGetDescr(r), values, isnull);
|
||||||
itup->t_tid = *ht_ctid;
|
itup->t_tid = *ht_ctid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -245,7 +239,7 @@ rtinsert(PG_FUNCTION_ARGS)
|
||||||
if (IndexTupleHasNulls(itup))
|
if (IndexTupleHasNulls(itup))
|
||||||
{
|
{
|
||||||
pfree(itup);
|
pfree(itup);
|
||||||
PG_RETURN_POINTER(NULL);
|
PG_RETURN_BOOL(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
initRtstate(&rtState, r);
|
initRtstate(&rtState, r);
|
||||||
|
@ -255,13 +249,12 @@ rtinsert(PG_FUNCTION_ARGS)
|
||||||
* have acquired exclusive lock on index relation. We need no locking
|
* have acquired exclusive lock on index relation. We need no locking
|
||||||
* here.
|
* here.
|
||||||
*/
|
*/
|
||||||
|
rtdoinsert(r, itup, &rtState);
|
||||||
|
|
||||||
res = rtdoinsert(r, itup, &rtState);
|
PG_RETURN_BOOL(true);
|
||||||
|
|
||||||
PG_RETURN_POINTER(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static InsertIndexResult
|
static void
|
||||||
rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
|
rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
|
||||||
{
|
{
|
||||||
Page page;
|
Page page;
|
||||||
|
@ -270,7 +263,6 @@ rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
|
||||||
IndexTuple which;
|
IndexTuple which;
|
||||||
OffsetNumber l;
|
OffsetNumber l;
|
||||||
RTSTACK *stack;
|
RTSTACK *stack;
|
||||||
InsertIndexResult res;
|
|
||||||
RTreePageOpaque opaque;
|
RTreePageOpaque opaque;
|
||||||
Datum datum;
|
Datum datum;
|
||||||
|
|
||||||
|
@ -305,10 +297,10 @@ rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
|
||||||
if (nospace(page, itup))
|
if (nospace(page, itup))
|
||||||
{
|
{
|
||||||
/* need to do a split */
|
/* need to do a split */
|
||||||
res = rtdosplit(r, buffer, stack, itup, rtstate);
|
rtdosplit(r, buffer, stack, itup, rtstate);
|
||||||
freestack(stack);
|
freestack(stack);
|
||||||
WriteBuffer(buffer); /* don't forget to release buffer! */
|
WriteBuffer(buffer); /* don't forget to release buffer! */
|
||||||
return res;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add the item and write the buffer */
|
/* add the item and write the buffer */
|
||||||
|
@ -335,12 +327,6 @@ rtdoinsert(Relation r, IndexTuple itup, RTSTATE *rtstate)
|
||||||
/* now expand the page boundary in the parent to include the new child */
|
/* now expand the page boundary in the parent to include the new child */
|
||||||
rttighten(r, stack, datum, IndexTupleAttSize(itup), rtstate);
|
rttighten(r, stack, datum, IndexTupleAttSize(itup), rtstate);
|
||||||
freestack(stack);
|
freestack(stack);
|
||||||
|
|
||||||
/* build and return an InsertIndexResult for this insertion */
|
|
||||||
res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
|
|
||||||
ItemPointerSet(&(res->pointerData), blk, l);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -422,7 +408,7 @@ rttighten(Relation r,
|
||||||
* rtpicksplit does the interesting work of choosing the split.
|
* rtpicksplit does the interesting work of choosing the split.
|
||||||
* This routine just does the bit-pushing.
|
* This routine just does the bit-pushing.
|
||||||
*/
|
*/
|
||||||
static InsertIndexResult
|
static void
|
||||||
rtdosplit(Relation r,
|
rtdosplit(Relation r,
|
||||||
Buffer buffer,
|
Buffer buffer,
|
||||||
RTSTACK *stack,
|
RTSTACK *stack,
|
||||||
|
@ -446,9 +432,7 @@ rtdosplit(Relation r,
|
||||||
rbknum;
|
rbknum;
|
||||||
BlockNumber bufblock;
|
BlockNumber bufblock;
|
||||||
RTreePageOpaque opaque;
|
RTreePageOpaque opaque;
|
||||||
int blank;
|
bool *isnull;
|
||||||
InsertIndexResult res;
|
|
||||||
char *isnull;
|
|
||||||
SPLITVEC v;
|
SPLITVEC v;
|
||||||
OffsetNumber *spl_left,
|
OffsetNumber *spl_left,
|
||||||
*spl_right;
|
*spl_right;
|
||||||
|
@ -493,9 +477,6 @@ rtdosplit(Relation r,
|
||||||
maxoff = PageGetMaxOffsetNumber(p);
|
maxoff = PageGetMaxOffsetNumber(p);
|
||||||
newitemoff = OffsetNumberNext(maxoff);
|
newitemoff = OffsetNumberNext(maxoff);
|
||||||
|
|
||||||
/* build an InsertIndexResult for this insertion */
|
|
||||||
res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* spl_left contains a list of the offset numbers of the tuples that
|
* spl_left contains a list of the offset numbers of the tuples that
|
||||||
* will go to the left page. For each offset number, get the tuple
|
* will go to the left page. For each offset number, get the tuple
|
||||||
|
@ -521,9 +502,6 @@ rtdosplit(Relation r,
|
||||||
RelationGetRelationName(r));
|
RelationGetRelationName(r));
|
||||||
leftoff = OffsetNumberNext(leftoff);
|
leftoff = OffsetNumberNext(leftoff);
|
||||||
|
|
||||||
if (i == newitemoff)
|
|
||||||
ItemPointerSet(&(res->pointerData), lbknum, leftoff);
|
|
||||||
|
|
||||||
spl_left++; /* advance in left split vector */
|
spl_left++; /* advance in left split vector */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,9 +523,6 @@ rtdosplit(Relation r,
|
||||||
RelationGetRelationName(r));
|
RelationGetRelationName(r));
|
||||||
rightoff = OffsetNumberNext(rightoff);
|
rightoff = OffsetNumberNext(rightoff);
|
||||||
|
|
||||||
if (i == newitemoff)
|
|
||||||
ItemPointerSet(&(res->pointerData), rbknum, rightoff);
|
|
||||||
|
|
||||||
spl_right++; /* advance in right split vector */
|
spl_right++; /* advance in right split vector */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,14 +557,12 @@ rtdosplit(Relation r,
|
||||||
rtadjscans(r, RTOP_SPLIT, bufblock, FirstOffsetNumber);
|
rtadjscans(r, RTOP_SPLIT, bufblock, FirstOffsetNumber);
|
||||||
|
|
||||||
tupDesc = r->rd_att;
|
tupDesc = r->rd_att;
|
||||||
isnull = (char *) palloc(r->rd_rel->relnatts);
|
isnull = (bool *) palloc(r->rd_rel->relnatts * sizeof(bool));
|
||||||
for (blank = 0; blank < r->rd_rel->relnatts; blank++)
|
memset(isnull, false, r->rd_rel->relnatts * sizeof(bool));
|
||||||
isnull[blank] = ' ';
|
|
||||||
|
ltup = index_form_tuple(tupDesc, &(v.spl_ldatum), isnull);
|
||||||
|
rtup = index_form_tuple(tupDesc, &(v.spl_rdatum), isnull);
|
||||||
|
|
||||||
ltup = (IndexTuple) index_formtuple(tupDesc,
|
|
||||||
&(v.spl_ldatum), isnull);
|
|
||||||
rtup = (IndexTuple) index_formtuple(tupDesc,
|
|
||||||
&(v.spl_rdatum), isnull);
|
|
||||||
pfree(isnull);
|
pfree(isnull);
|
||||||
pfree(DatumGetPointer(v.spl_ldatum));
|
pfree(DatumGetPointer(v.spl_ldatum));
|
||||||
pfree(DatumGetPointer(v.spl_rdatum));
|
pfree(DatumGetPointer(v.spl_rdatum));
|
||||||
|
@ -602,8 +575,6 @@ rtdosplit(Relation r,
|
||||||
|
|
||||||
pfree(ltup);
|
pfree(ltup);
|
||||||
pfree(rtup);
|
pfree(rtup);
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -619,7 +590,6 @@ rtintinsert(Relation r,
|
||||||
Datum ldatum,
|
Datum ldatum,
|
||||||
rdatum,
|
rdatum,
|
||||||
newdatum;
|
newdatum;
|
||||||
InsertIndexResult res;
|
|
||||||
|
|
||||||
if (stk == NULL)
|
if (stk == NULL)
|
||||||
{
|
{
|
||||||
|
@ -651,10 +621,9 @@ rtintinsert(Relation r,
|
||||||
newdatum = IndexTupleGetDatum(ltup);
|
newdatum = IndexTupleGetDatum(ltup);
|
||||||
rttighten(r, stk->rts_parent, newdatum,
|
rttighten(r, stk->rts_parent, newdatum,
|
||||||
IndexTupleAttSize(ltup), rtstate);
|
IndexTupleAttSize(ltup), rtstate);
|
||||||
res = rtdosplit(r, b, stk->rts_parent, rtup, rtstate);
|
rtdosplit(r, b, stk->rts_parent, rtup, rtstate);
|
||||||
WriteBuffer(b); /* don't forget to release buffer! -
|
WriteBuffer(b); /* don't forget to release buffer! -
|
||||||
* 01/31/94 */
|
* 01/31/94 */
|
||||||
pfree(res);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.248 2005/03/20 22:00:51 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.249 2005/03/21 01:24:01 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
|
@ -889,28 +889,29 @@ BuildIndexInfo(Relation index)
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* FormIndexDatum
|
* FormIndexDatum
|
||||||
* Construct Datum[] and nullv[] arrays for a new index tuple.
|
* Construct values[] and isnull[] arrays for a new index tuple.
|
||||||
*
|
*
|
||||||
* indexInfo Info about the index
|
* indexInfo Info about the index
|
||||||
* slot Heap tuple for which we must prepare an index entry
|
* slot Heap tuple for which we must prepare an index entry
|
||||||
* estate executor state for evaluating any index expressions
|
* estate executor state for evaluating any index expressions
|
||||||
* datum Array of index Datums (output area)
|
* values Array of index Datums (output area)
|
||||||
* nullv Array of is-null indicators (output area)
|
* isnull Array of is-null indicators (output area)
|
||||||
*
|
*
|
||||||
* When there are no index expressions, estate may be NULL. Otherwise it
|
* When there are no index expressions, estate may be NULL. Otherwise it
|
||||||
* must be supplied, *and* the ecxt_scantuple slot of its per-tuple expr
|
* must be supplied, *and* the ecxt_scantuple slot of its per-tuple expr
|
||||||
* context must point to the heap tuple passed in.
|
* context must point to the heap tuple passed in.
|
||||||
*
|
*
|
||||||
* For largely historical reasons, we don't actually call index_formtuple()
|
* Notice we don't actually call index_form_tuple() here; we just prepare
|
||||||
* here, we just prepare its input arrays datum[] and nullv[].
|
* its input arrays values[] and isnull[]. This is because the index AM
|
||||||
|
* may wish to alter the data before storage.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
FormIndexDatum(IndexInfo *indexInfo,
|
FormIndexDatum(IndexInfo *indexInfo,
|
||||||
TupleTableSlot *slot,
|
TupleTableSlot *slot,
|
||||||
EState *estate,
|
EState *estate,
|
||||||
Datum *datum,
|
Datum *values,
|
||||||
char *nullv)
|
bool *isnull)
|
||||||
{
|
{
|
||||||
ListCell *indexpr_item;
|
ListCell *indexpr_item;
|
||||||
int i;
|
int i;
|
||||||
|
@ -954,8 +955,8 @@ FormIndexDatum(IndexInfo *indexInfo,
|
||||||
NULL);
|
NULL);
|
||||||
indexpr_item = lnext(indexpr_item);
|
indexpr_item = lnext(indexpr_item);
|
||||||
}
|
}
|
||||||
datum[i] = iDatum;
|
values[i] = iDatum;
|
||||||
nullv[i] = (isNull) ? 'n' : ' ';
|
isnull[i] = isNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexpr_item != NULL)
|
if (indexpr_item != NULL)
|
||||||
|
@ -1332,8 +1333,8 @@ IndexBuildHeapScan(Relation heapRelation,
|
||||||
{
|
{
|
||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
HeapTuple heapTuple;
|
HeapTuple heapTuple;
|
||||||
Datum attdata[INDEX_MAX_KEYS];
|
Datum values[INDEX_MAX_KEYS];
|
||||||
char nulls[INDEX_MAX_KEYS];
|
bool isnull[INDEX_MAX_KEYS];
|
||||||
double reltuples;
|
double reltuples;
|
||||||
List *predicate;
|
List *predicate;
|
||||||
TupleTableSlot *slot;
|
TupleTableSlot *slot;
|
||||||
|
@ -1509,17 +1510,17 @@ IndexBuildHeapScan(Relation heapRelation,
|
||||||
FormIndexDatum(indexInfo,
|
FormIndexDatum(indexInfo,
|
||||||
slot,
|
slot,
|
||||||
estate,
|
estate,
|
||||||
attdata,
|
values,
|
||||||
nulls);
|
isnull);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* You'd think we should go ahead and build the index tuple here,
|
* You'd think we should go ahead and build the index tuple here,
|
||||||
* but some index AMs want to do further processing on the data
|
* but some index AMs want to do further processing on the data
|
||||||
* first. So pass the attdata and nulls arrays, instead.
|
* first. So pass the values[] and isnull[] arrays, instead.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Call the AM's callback routine to process the tuple */
|
/* Call the AM's callback routine to process the tuple */
|
||||||
callback(indexRelation, heapTuple, attdata, nulls, tupleIsAlive,
|
callback(indexRelation, heapTuple, values, isnull, tupleIsAlive,
|
||||||
callback_state);
|
callback_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/indexing.c,v 1.108 2005/03/16 21:38:04 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/indexing.c,v 1.109 2005/03/21 01:24:01 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -75,8 +75,8 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
|
||||||
Relation heapRelation;
|
Relation heapRelation;
|
||||||
TupleTableSlot *slot;
|
TupleTableSlot *slot;
|
||||||
IndexInfo **indexInfoArray;
|
IndexInfo **indexInfoArray;
|
||||||
Datum datum[INDEX_MAX_KEYS];
|
Datum values[INDEX_MAX_KEYS];
|
||||||
char nullv[INDEX_MAX_KEYS];
|
bool isnull[INDEX_MAX_KEYS];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get information from the state structure. Fall out if nothing to do.
|
* Get information from the state structure. Fall out if nothing to do.
|
||||||
|
@ -98,7 +98,6 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
|
||||||
for (i = 0; i < numIndexes; i++)
|
for (i = 0; i < numIndexes; i++)
|
||||||
{
|
{
|
||||||
IndexInfo *indexInfo;
|
IndexInfo *indexInfo;
|
||||||
InsertIndexResult result;
|
|
||||||
|
|
||||||
indexInfo = indexInfoArray[i];
|
indexInfo = indexInfoArray[i];
|
||||||
|
|
||||||
|
@ -110,27 +109,24 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
|
||||||
Assert(indexInfo->ii_Predicate == NIL);
|
Assert(indexInfo->ii_Predicate == NIL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FormIndexDatum fills in its datum and null parameters with
|
* FormIndexDatum fills in its values and isnull parameters with
|
||||||
* attribute information taken from the given tuple.
|
* the appropriate values for the column(s) of the index.
|
||||||
*/
|
*/
|
||||||
FormIndexDatum(indexInfo,
|
FormIndexDatum(indexInfo,
|
||||||
slot,
|
slot,
|
||||||
NULL, /* no expression eval to do */
|
NULL, /* no expression eval to do */
|
||||||
datum,
|
values,
|
||||||
nullv);
|
isnull);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The index AM does the rest.
|
* The index AM does the rest.
|
||||||
*/
|
*/
|
||||||
result = index_insert(relationDescs[i], /* index relation */
|
index_insert(relationDescs[i], /* index relation */
|
||||||
datum, /* array of heaptuple Datums */
|
values, /* array of index Datums */
|
||||||
nullv, /* info on nulls */
|
isnull, /* is-null flags */
|
||||||
&(heapTuple->t_self), /* tid of heap tuple */
|
&(heapTuple->t_self), /* tid of heap tuple */
|
||||||
heapRelation,
|
heapRelation,
|
||||||
relationDescs[i]->rd_index->indisunique);
|
relationDescs[i]->rd_index->indisunique);
|
||||||
|
|
||||||
if (result)
|
|
||||||
pfree(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecDropSingleTupleTableSlot(slot);
|
ExecDropSingleTupleTableSlot(slot);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.83 2005/03/16 21:38:05 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.84 2005/03/21 01:24:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -448,8 +448,8 @@ compute_index_stats(Relation onerel, double totalrows,
|
||||||
{
|
{
|
||||||
MemoryContext ind_context,
|
MemoryContext ind_context,
|
||||||
old_context;
|
old_context;
|
||||||
Datum attdata[INDEX_MAX_KEYS];
|
Datum values[INDEX_MAX_KEYS];
|
||||||
char nulls[INDEX_MAX_KEYS];
|
bool isnull[INDEX_MAX_KEYS];
|
||||||
int ind,
|
int ind,
|
||||||
i;
|
i;
|
||||||
|
|
||||||
|
@ -528,8 +528,8 @@ compute_index_stats(Relation onerel, double totalrows,
|
||||||
FormIndexDatum(indexInfo,
|
FormIndexDatum(indexInfo,
|
||||||
slot,
|
slot,
|
||||||
estate,
|
estate,
|
||||||
attdata,
|
values,
|
||||||
nulls);
|
isnull);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save just the columns we care about.
|
* Save just the columns we care about.
|
||||||
|
@ -539,8 +539,8 @@ compute_index_stats(Relation onerel, double totalrows,
|
||||||
VacAttrStats *stats = thisdata->vacattrstats[i];
|
VacAttrStats *stats = thisdata->vacattrstats[i];
|
||||||
int attnum = stats->attr->attnum;
|
int attnum = stats->attr->attnum;
|
||||||
|
|
||||||
exprvals[tcnt] = attdata[attnum - 1];
|
exprvals[tcnt] = values[attnum - 1];
|
||||||
exprnulls[tcnt] = (nulls[attnum - 1] == 'n');
|
exprnulls[tcnt] = isnull[attnum - 1];
|
||||||
tcnt++;
|
tcnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.118 2005/03/16 21:38:07 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.119 2005/03/21 01:24:03 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -861,8 +861,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
|
||||||
Relation heapRelation;
|
Relation heapRelation;
|
||||||
IndexInfo **indexInfoArray;
|
IndexInfo **indexInfoArray;
|
||||||
ExprContext *econtext;
|
ExprContext *econtext;
|
||||||
Datum datum[INDEX_MAX_KEYS];
|
Datum values[INDEX_MAX_KEYS];
|
||||||
char nullv[INDEX_MAX_KEYS];
|
bool isnull[INDEX_MAX_KEYS];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get information from the result relation info structure.
|
* Get information from the result relation info structure.
|
||||||
|
@ -889,7 +889,6 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
|
||||||
for (i = 0; i < numIndices; i++)
|
for (i = 0; i < numIndices; i++)
|
||||||
{
|
{
|
||||||
IndexInfo *indexInfo;
|
IndexInfo *indexInfo;
|
||||||
InsertIndexResult result;
|
|
||||||
|
|
||||||
if (relationDescs[i] == NULL)
|
if (relationDescs[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -920,35 +919,31 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FormIndexDatum fills in its datum and null parameters with
|
* FormIndexDatum fills in its values and isnull parameters with
|
||||||
* attribute information taken from the given tuple. It also
|
* the appropriate values for the column(s) of the index.
|
||||||
* computes any expressions needed.
|
|
||||||
*/
|
*/
|
||||||
FormIndexDatum(indexInfo,
|
FormIndexDatum(indexInfo,
|
||||||
slot,
|
slot,
|
||||||
estate,
|
estate,
|
||||||
datum,
|
values,
|
||||||
nullv);
|
isnull);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The index AM does the rest. Note we suppress unique-index
|
* The index AM does the rest. Note we suppress unique-index
|
||||||
* checks if we are being called from VACUUM, since VACUUM may
|
* checks if we are being called from VACUUM, since VACUUM may
|
||||||
* need to move dead tuples that have the same keys as live ones.
|
* need to move dead tuples that have the same keys as live ones.
|
||||||
*/
|
*/
|
||||||
result = index_insert(relationDescs[i], /* index relation */
|
index_insert(relationDescs[i], /* index relation */
|
||||||
datum, /* array of index Datums */
|
values, /* array of index Datums */
|
||||||
nullv, /* info on nulls */
|
isnull, /* null flags */
|
||||||
tupleid, /* tid of heap tuple */
|
tupleid, /* tid of heap tuple */
|
||||||
heapRelation,
|
heapRelation,
|
||||||
relationDescs[i]->rd_index->indisunique && !is_vacuum);
|
relationDescs[i]->rd_index->indisunique && !is_vacuum);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* keep track of index inserts for debugging
|
* keep track of index inserts for debugging
|
||||||
*/
|
*/
|
||||||
IncrIndexInserted();
|
IncrIndexInserted();
|
||||||
|
|
||||||
if (result)
|
|
||||||
pfree(result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.47 2004/12/31 22:03:21 pgsql Exp $
|
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.48 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -72,8 +72,8 @@ extern Relation index_open(Oid relationId);
|
||||||
extern Relation index_openrv(const RangeVar *relation);
|
extern Relation index_openrv(const RangeVar *relation);
|
||||||
extern Relation index_openr(const char *sysRelationName);
|
extern Relation index_openr(const char *sysRelationName);
|
||||||
extern void index_close(Relation relation);
|
extern void index_close(Relation relation);
|
||||||
extern InsertIndexResult index_insert(Relation indexRelation,
|
extern bool index_insert(Relation indexRelation,
|
||||||
Datum *datums, char *nulls,
|
Datum *values, bool *isnull,
|
||||||
ItemPointer heap_t_ctid,
|
ItemPointer heap_t_ctid,
|
||||||
Relation heapRelation,
|
Relation heapRelation,
|
||||||
bool check_uniqueness);
|
bool check_uniqueness);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.59 2004/12/31 22:03:21 pgsql Exp $
|
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.60 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* modeled after Margo Seltzer's hash implementation for unix.
|
* modeled after Margo Seltzer's hash implementation for unix.
|
||||||
|
@ -266,7 +266,7 @@ extern Datum hash_any(register const unsigned char *k, register int keylen);
|
||||||
/* private routines */
|
/* private routines */
|
||||||
|
|
||||||
/* hashinsert.c */
|
/* hashinsert.c */
|
||||||
extern InsertIndexResult _hash_doinsert(Relation rel, HashItem hitem);
|
extern void _hash_doinsert(Relation rel, HashItem hitem);
|
||||||
|
|
||||||
/* hashovfl.c */
|
/* hashovfl.c */
|
||||||
extern Buffer _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf);
|
extern Buffer _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.97 2005/03/20 23:40:29 neilc Exp $
|
* $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.98 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -180,13 +180,9 @@ extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf,
|
||||||
/* in common/heaptuple.c */
|
/* in common/heaptuple.c */
|
||||||
extern Size heap_compute_data_size(TupleDesc tupleDesc,
|
extern Size heap_compute_data_size(TupleDesc tupleDesc,
|
||||||
Datum *values, bool *isnull);
|
Datum *values, bool *isnull);
|
||||||
extern Size ComputeDataSize(TupleDesc tupleDesc, Datum *values, char *nulls);
|
|
||||||
extern void heap_fill_tuple(TupleDesc tupleDesc,
|
extern void heap_fill_tuple(TupleDesc tupleDesc,
|
||||||
Datum *values, bool *isnull,
|
Datum *values, bool *isnull,
|
||||||
char *data, uint16 *infomask, bits8 *bit);
|
char *data, uint16 *infomask, bits8 *bit);
|
||||||
extern void DataFill(char *data, TupleDesc tupleDesc,
|
|
||||||
Datum *values, char *nulls, uint16 *infomask,
|
|
||||||
bits8 *bit);
|
|
||||||
extern bool heap_attisnull(HeapTuple tup, int attnum);
|
extern bool heap_attisnull(HeapTuple tup, int attnum);
|
||||||
extern Datum nocachegetattr(HeapTuple tup, int attnum,
|
extern Datum nocachegetattr(HeapTuple tup, int attnum,
|
||||||
TupleDesc att, bool *isnull);
|
TupleDesc att, bool *isnull);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/itup.h,v 1.41 2004/12/31 22:03:21 pgsql Exp $
|
* $PostgreSQL: pgsql/src/include/access/itup.h,v 1.42 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -46,14 +46,6 @@ typedef struct IndexTupleData
|
||||||
typedef IndexTupleData *IndexTuple;
|
typedef IndexTupleData *IndexTuple;
|
||||||
|
|
||||||
|
|
||||||
typedef struct InsertIndexResultData
|
|
||||||
{
|
|
||||||
ItemPointerData pointerData;
|
|
||||||
} InsertIndexResultData;
|
|
||||||
|
|
||||||
typedef InsertIndexResultData *InsertIndexResult;
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* externs
|
* externs
|
||||||
* ----------------
|
* ----------------
|
||||||
|
@ -73,7 +65,7 @@ typedef InsertIndexResultData *InsertIndexResult;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Takes an infomask as argument (primarily because this needs to be usable
|
* Takes an infomask as argument (primarily because this needs to be usable
|
||||||
* at index_formtuple time so enough space is allocated).
|
* at index_form_tuple time so enough space is allocated).
|
||||||
*
|
*
|
||||||
* Change me if adding an attribute to IndexTuples!!!!!!!!!!!
|
* Change me if adding an attribute to IndexTuples!!!!!!!!!!!
|
||||||
*/
|
*/
|
||||||
|
@ -134,8 +126,8 @@ typedef InsertIndexResultData *InsertIndexResult;
|
||||||
|
|
||||||
|
|
||||||
/* routines in indextuple.c */
|
/* routines in indextuple.c */
|
||||||
extern IndexTuple index_formtuple(TupleDesc tupleDescriptor,
|
extern IndexTuple index_form_tuple(TupleDesc tupleDescriptor,
|
||||||
Datum *value, char *null);
|
Datum *values, bool *isnull);
|
||||||
extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
|
extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
|
||||||
TupleDesc tupleDesc, bool *isnull);
|
TupleDesc tupleDesc, bool *isnull);
|
||||||
extern IndexTuple CopyIndexTuple(IndexTuple source);
|
extern IndexTuple CopyIndexTuple(IndexTuple source);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.83 2004/12/31 22:03:21 pgsql Exp $
|
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.84 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -416,7 +416,7 @@ extern Datum btvacuumcleanup(PG_FUNCTION_ARGS);
|
||||||
/*
|
/*
|
||||||
* prototypes for functions in nbtinsert.c
|
* prototypes for functions in nbtinsert.c
|
||||||
*/
|
*/
|
||||||
extern InsertIndexResult _bt_doinsert(Relation rel, BTItem btitem,
|
extern void _bt_doinsert(Relation rel, BTItem btitem,
|
||||||
bool index_is_unique, Relation heapRel);
|
bool index_is_unique, Relation heapRel);
|
||||||
extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, int access);
|
extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, int access);
|
||||||
extern void _bt_insert_parent(Relation rel, Buffer buf, Buffer rbuf,
|
extern void _bt_insert_parent(Relation rel, Buffer buf, Buffer rbuf,
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.21 2005/01/01 05:43:09 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.22 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
/*
|
/*
|
||||||
* If an index value is larger than TOAST_INDEX_TARGET, we will try to
|
* If an index value is larger than TOAST_INDEX_TARGET, we will try to
|
||||||
* compress it (we can't move it out-of-line, however). Note that this
|
* compress it (we can't move it out-of-line, however). Note that this
|
||||||
* number is per-datum, not per-tuple, for simplicity in index_formtuple().
|
* number is per-datum, not per-tuple, for simplicity in index_form_tuple().
|
||||||
*/
|
*/
|
||||||
#define TOAST_INDEX_TARGET (MaxTupleSize / 16)
|
#define TOAST_INDEX_TARGET (MaxTupleSize / 16)
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.258 2005/03/16 22:59:42 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.259 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -53,6 +53,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 200503161
|
#define CATALOG_VERSION_NO 200503201
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.60 2005/03/16 21:38:09 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.61 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -23,11 +23,11 @@
|
||||||
|
|
||||||
/* Typedef for callback function for IndexBuildHeapScan */
|
/* Typedef for callback function for IndexBuildHeapScan */
|
||||||
typedef void (*IndexBuildCallback) (Relation index,
|
typedef void (*IndexBuildCallback) (Relation index,
|
||||||
HeapTuple htup,
|
HeapTuple htup,
|
||||||
Datum *attdata,
|
Datum *values,
|
||||||
char *nulls,
|
bool *isnull,
|
||||||
bool tupleIsAlive,
|
bool tupleIsAlive,
|
||||||
void *state);
|
void *state);
|
||||||
|
|
||||||
|
|
||||||
extern Oid index_create(Oid heapRelationId,
|
extern Oid index_create(Oid heapRelationId,
|
||||||
|
@ -48,8 +48,8 @@ extern IndexInfo *BuildIndexInfo(Relation index);
|
||||||
extern void FormIndexDatum(IndexInfo *indexInfo,
|
extern void FormIndexDatum(IndexInfo *indexInfo,
|
||||||
TupleTableSlot *slot,
|
TupleTableSlot *slot,
|
||||||
EState *estate,
|
EState *estate,
|
||||||
Datum *datum,
|
Datum *values,
|
||||||
char *nullv);
|
bool *isnull);
|
||||||
|
|
||||||
extern void UpdateStats(Oid relid, double reltuples);
|
extern void UpdateStats(Oid relid, double reltuples);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.352 2005/02/28 03:45:22 neilc Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.353 2005/03/21 01:24:04 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The script catalog/genbki.sh reads this file and generates .bki
|
* The script catalog/genbki.sh reads this file and generates .bki
|
||||||
|
@ -660,7 +660,7 @@ DESCR("convert int4 to float4");
|
||||||
DATA(insert OID = 319 ( int4 PGNSP PGUID 12 f f t f i 1 23 "700" _null_ ftoi4 - _null_ ));
|
DATA(insert OID = 319 ( int4 PGNSP PGUID 12 f f t f i 1 23 "700" _null_ ftoi4 - _null_ ));
|
||||||
DESCR("convert float4 to int4");
|
DESCR("convert float4 to int4");
|
||||||
|
|
||||||
DATA(insert OID = 320 ( rtinsert PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" _null_ rtinsert - _null_ ));
|
DATA(insert OID = 320 ( rtinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ rtinsert - _null_ ));
|
||||||
DESCR("r-tree(internal)");
|
DESCR("r-tree(internal)");
|
||||||
DATA(insert OID = 322 ( rtgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ rtgettuple - _null_ ));
|
DATA(insert OID = 322 ( rtgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ rtgettuple - _null_ ));
|
||||||
DESCR("r-tree(internal)");
|
DESCR("r-tree(internal)");
|
||||||
|
@ -683,7 +683,7 @@ DESCR("r-tree(internal)");
|
||||||
|
|
||||||
DATA(insert OID = 330 ( btgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ btgettuple - _null_ ));
|
DATA(insert OID = 330 ( btgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ btgettuple - _null_ ));
|
||||||
DESCR("btree(internal)");
|
DESCR("btree(internal)");
|
||||||
DATA(insert OID = 331 ( btinsert PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" _null_ btinsert - _null_ ));
|
DATA(insert OID = 331 ( btinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ btinsert - _null_ ));
|
||||||
DESCR("btree(internal)");
|
DESCR("btree(internal)");
|
||||||
DATA(insert OID = 333 ( btbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ btbeginscan - _null_ ));
|
DATA(insert OID = 333 ( btbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ btbeginscan - _null_ ));
|
||||||
DESCR("btree(internal)");
|
DESCR("btree(internal)");
|
||||||
|
@ -798,7 +798,7 @@ DESCR("convert char(n) to name");
|
||||||
|
|
||||||
DATA(insert OID = 440 ( hashgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ hashgettuple - _null_ ));
|
DATA(insert OID = 440 ( hashgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ hashgettuple - _null_ ));
|
||||||
DESCR("hash(internal)");
|
DESCR("hash(internal)");
|
||||||
DATA(insert OID = 441 ( hashinsert PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" _null_ hashinsert - _null_ ));
|
DATA(insert OID = 441 ( hashinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ hashinsert - _null_ ));
|
||||||
DESCR("hash(internal)");
|
DESCR("hash(internal)");
|
||||||
DATA(insert OID = 443 ( hashbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ hashbeginscan - _null_ ));
|
DATA(insert OID = 443 ( hashbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ hashbeginscan - _null_ ));
|
||||||
DESCR("hash(internal)");
|
DESCR("hash(internal)");
|
||||||
|
@ -1060,7 +1060,7 @@ DESCR("smaller of two");
|
||||||
|
|
||||||
DATA(insert OID = 774 ( gistgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ gistgettuple - _null_ ));
|
DATA(insert OID = 774 ( gistgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ gistgettuple - _null_ ));
|
||||||
DESCR("gist(internal)");
|
DESCR("gist(internal)");
|
||||||
DATA(insert OID = 775 ( gistinsert PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" _null_ gistinsert - _null_ ));
|
DATA(insert OID = 775 ( gistinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ gistinsert - _null_ ));
|
||||||
DESCR("gist(internal)");
|
DESCR("gist(internal)");
|
||||||
DATA(insert OID = 777 ( gistbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ gistbeginscan - _null_ ));
|
DATA(insert OID = 777 ( gistbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ gistbeginscan - _null_ ));
|
||||||
DESCR("gist(internal)");
|
DESCR("gist(internal)");
|
||||||
|
|
Loading…
Reference in New Issue