Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.137
diff -c -r2.137 catalogs.sgml
*** doc/src/sgml/catalogs.sgml 12 Nov 2006 06:25:37 -0000 2.137
--- doc/src/sgml/catalogs.sgml 27 Nov 2006 14:27:40 -0000
***************
*** 499,504 ****
--- 499,511 ----
Function to parse and validate reloptions> for an index
+
+ amsuggestblock
+ regproc
+ pg_proc.oid
+ Get the best place in the heap to put a new tuple
+
+
Index: doc/src/sgml/indexam.sgml
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/doc/src/sgml/indexam.sgml,v
retrieving revision 2.18
diff -c -r2.18 indexam.sgml
*** doc/src/sgml/indexam.sgml 16 Sep 2006 00:30:14 -0000 2.18
--- doc/src/sgml/indexam.sgml 27 Nov 2006 14:27:40 -0000
***************
*** 391,396 ****
--- 391,414 ----
amoptions> to test validity of options settings.
+
+
+ BlockNumber
+ amsuggestblock (Relation indexRelation,
+ Datum *values,
+ bool *isnull,
+ Relation heapRelation);
+
+ Gets the optimal place in the heap for a new tuple. The parameters
+ correspond the parameters for aminsert.
+ This function is called on the clustered index before a new tuple
+ is inserted to the heap, and it should choose the optimal insertion
+ target page on the heap in such manner that the heap stays as close
+ as possible to the index order.
+ amsuggestblock can return InvalidBlockNumber if
+ the index am doesn't have a suggestion.
+
+
Index: src/backend/access/heap/heapam.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/heap/heapam.c,v
retrieving revision 1.222
diff -c -r1.222 heapam.c
*** src/backend/access/heap/heapam.c 17 Nov 2006 18:00:14 -0000 1.222
--- src/backend/access/heap/heapam.c 27 Nov 2006 14:27:40 -0000
***************
*** 1363,1368 ****
--- 1363,1373 ----
* use_fsm is passed directly to RelationGetBufferForTuple, which see for
* more info.
*
+ * suggested_blk can be set by the caller to hint heap_insert which
+ * block would be the best place to put the new tuple in. heap_insert can
+ * ignore the suggestion, if there's not enough room on that block.
+ * InvalidBlockNumber means no preference.
+ *
* The return value is the OID assigned to the tuple (either here or by the
* caller), or InvalidOid if no OID. The header fields of *tup are updated
* to match the stored tuple; in particular tup->t_self receives the actual
***************
*** 1371,1377 ****
*/
Oid
heap_insert(Relation relation, HeapTuple tup, CommandId cid,
! bool use_wal, bool use_fsm)
{
TransactionId xid = GetCurrentTransactionId();
HeapTuple heaptup;
--- 1376,1382 ----
*/
Oid
heap_insert(Relation relation, HeapTuple tup, CommandId cid,
! bool use_wal, bool use_fsm, BlockNumber suggested_blk)
{
TransactionId xid = GetCurrentTransactionId();
HeapTuple heaptup;
***************
*** 1424,1430 ****
/* Find buffer to insert this tuple into */
buffer = RelationGetBufferForTuple(relation, heaptup->t_len,
! InvalidBuffer, use_fsm);
/* NO EREPORT(ERROR) from here till changes are logged */
START_CRIT_SECTION();
--- 1429,1435 ----
/* Find buffer to insert this tuple into */
buffer = RelationGetBufferForTuple(relation, heaptup->t_len,
! InvalidBuffer, use_fsm, suggested_blk);
/* NO EREPORT(ERROR) from here till changes are logged */
START_CRIT_SECTION();
***************
*** 1532,1538 ****
Oid
simple_heap_insert(Relation relation, HeapTuple tup)
{
! return heap_insert(relation, tup, GetCurrentCommandId(), true, true);
}
/*
--- 1537,1544 ----
Oid
simple_heap_insert(Relation relation, HeapTuple tup)
{
! return heap_insert(relation, tup, GetCurrentCommandId(), true,
! true, InvalidBlockNumber);
}
/*
***************
*** 2117,2123 ****
{
/* Assume there's no chance to put heaptup on same page. */
newbuf = RelationGetBufferForTuple(relation, heaptup->t_len,
! buffer, true);
}
else
{
--- 2123,2130 ----
{
/* Assume there's no chance to put heaptup on same page. */
newbuf = RelationGetBufferForTuple(relation, heaptup->t_len,
! buffer, true,
! InvalidBlockNumber);
}
else
{
***************
*** 2134,2140 ****
*/
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
newbuf = RelationGetBufferForTuple(relation, heaptup->t_len,
! buffer, true);
}
else
{
--- 2141,2148 ----
*/
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
newbuf = RelationGetBufferForTuple(relation, heaptup->t_len,
! buffer, true,
! InvalidBlockNumber);
}
else
{
Index: src/backend/access/heap/hio.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/heap/hio.c,v
retrieving revision 1.63
diff -c -r1.63 hio.c
*** src/backend/access/heap/hio.c 3 Jul 2006 22:45:37 -0000 1.63
--- src/backend/access/heap/hio.c 27 Nov 2006 14:27:40 -0000
***************
*** 93,98 ****
--- 93,100 ----
* any committed data of other transactions. (See heap_insert's comments
* for additional constraints needed for safe usage of this behavior.)
*
+ * If the caller has a suggestion, it's passed in suggestedBlock.
+ *
* We always try to avoid filling existing pages further than the fillfactor.
* This is OK since this routine is not consulted when updating a tuple and
* keeping it on the same page, which is the scenario fillfactor is meant
***************
*** 103,109 ****
*/
Buffer
RelationGetBufferForTuple(Relation relation, Size len,
! Buffer otherBuffer, bool use_fsm)
{
Buffer buffer = InvalidBuffer;
Page pageHeader;
--- 105,112 ----
*/
Buffer
RelationGetBufferForTuple(Relation relation, Size len,
! Buffer otherBuffer, bool use_fsm,
! BlockNumber suggestedBlock)
{
Buffer buffer = InvalidBuffer;
Page pageHeader;
***************
*** 135,142 ****
otherBlock = InvalidBlockNumber; /* just to keep compiler quiet */
/*
! * We first try to put the tuple on the same page we last inserted a tuple
! * on, as cached in the relcache entry. If that doesn't work, we ask the
* shared Free Space Map to locate a suitable page. Since the FSM's info
* might be out of date, we have to be prepared to loop around and retry
* multiple times. (To insure this isn't an infinite loop, we must update
--- 138,147 ----
otherBlock = InvalidBlockNumber; /* just to keep compiler quiet */
/*
! * We first try to put the tuple on the page suggested by the caller, if
! * any. Then we try to put the tuple on the same page we last inserted a
! * tuple on, as cached in the relcache entry. If that doesn't work, we
! * ask the
* shared Free Space Map to locate a suitable page. Since the FSM's info
* might be out of date, we have to be prepared to loop around and retry
* multiple times. (To insure this isn't an infinite loop, we must update
***************
*** 144,152 ****
* not to be suitable.) If the FSM has no record of a page with enough
* free space, we give up and extend the relation.
*
! * When use_fsm is false, we either put the tuple onto the existing target
! * page or extend the relation.
*/
if (len + saveFreeSpace <= MaxTupleSize)
targetBlock = relation->rd_targblock;
else
--- 149,167 ----
* not to be suitable.) If the FSM has no record of a page with enough
* free space, we give up and extend the relation.
*
! * When use_fsm is false, we skip the fsm lookup if neither the suggested
! * nor the cached last insertion page has enough room, and extend the
! * relation.
! *
! * The fillfactor is taken into account when calculating the free space
! * on the cached target block, and when using the FSM. The suggested page
! * is used whenever there's enough room in it, regardless of the fillfactor,
! * because that's exactly the purpose the space is reserved for in the
! * first place.
*/
+ if (suggestedBlock != InvalidBlockNumber)
+ targetBlock = suggestedBlock;
+ else
if (len + saveFreeSpace <= MaxTupleSize)
targetBlock = relation->rd_targblock;
else
***************
*** 219,224 ****
--- 234,244 ----
*/
pageHeader = (Page) BufferGetPage(buffer);
pageFreeSpace = PageGetFreeSpace(pageHeader);
+
+ /* If we're trying the suggested block, don't care about fillfactor */
+ if (targetBlock == suggestedBlock && len <= pageFreeSpace)
+ return buffer;
+
if (len + saveFreeSpace <= pageFreeSpace)
{
/* use this page as future insert target, too */
***************
*** 241,246 ****
--- 261,275 ----
ReleaseBuffer(buffer);
}
+ /* If we just tried the suggested block, try the cached target
+ * block next, before consulting the FSM. */
+ if(suggestedBlock == targetBlock)
+ {
+ targetBlock = relation->rd_targblock;
+ suggestedBlock = InvalidBlockNumber;
+ continue;
+ }
+
/* Without FSM, always fall out of the loop and extend */
if (!use_fsm)
break;
Index: src/backend/access/index/genam.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/index/genam.c,v
retrieving revision 1.59
diff -c -r1.59 genam.c
*** src/backend/access/index/genam.c 4 Oct 2006 00:29:48 -0000 1.59
--- src/backend/access/index/genam.c 27 Nov 2006 14:27:40 -0000
***************
*** 259,261 ****
--- 259,275 ----
pfree(sysscan);
}
+
+ /*
+ * This is a dummy implementation of amsuggestblock, to be used for index
+ * access methods that don't or can't support it. It just returns
+ * InvalidBlockNumber, which means "no preference".
+ *
+ * This is probably not a good best place for this function, but it doesn't
+ * fit naturally anywhere else either.
+ */
+ Datum
+ dummysuggestblock(PG_FUNCTION_ARGS)
+ {
+ PG_RETURN_UINT32(InvalidBlockNumber);
+ }
Index: src/backend/access/index/indexam.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/index/indexam.c,v
retrieving revision 1.95
diff -c -r1.95 indexam.c
*** src/backend/access/index/indexam.c 4 Oct 2006 00:29:48 -0000 1.95
--- src/backend/access/index/indexam.c 27 Nov 2006 14:27:40 -0000
***************
*** 18,23 ****
--- 18,24 ----
* index_rescan - restart a scan of an index
* index_endscan - end a scan
* index_insert - insert an index tuple into a relation
+ * index_suggestblock - get desired insert location for a heap tuple
* index_markpos - mark a scan position
* index_restrpos - restore a scan position
* index_getnext - get the next tuple from a scan
***************
*** 202,207 ****
--- 203,237 ----
BoolGetDatum(check_uniqueness)));
}
+ /* ----------------
+ * index_suggestblock - get desired insert location for a heap tuple
+ *
+ * The returned BlockNumber is the *heap* page that is the best place
+ * to insert the given tuple to, according to the index am. The best
+ * place is usually one that maintains the cluster order.
+ * ----------------
+ */
+ BlockNumber
+ index_suggestblock(Relation indexRelation,
+ Datum *values,
+ bool *isnull,
+ Relation heapRelation)
+ {
+ FmgrInfo *procedure;
+
+ RELATION_CHECKS;
+ GET_REL_PROCEDURE(amsuggestblock);
+
+ /*
+ * have the am's suggestblock proc do all the work.
+ */
+ return DatumGetUInt32(FunctionCall4(procedure,
+ PointerGetDatum(indexRelation),
+ PointerGetDatum(values),
+ PointerGetDatum(isnull),
+ PointerGetDatum(heapRelation)));
+ }
+
/*
* index_beginscan - start a scan of an index with amgettuple
*
Index: src/backend/access/nbtree/nbtinsert.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/nbtree/nbtinsert.c,v
retrieving revision 1.146
diff -c -r1.146 nbtinsert.c
*** src/backend/access/nbtree/nbtinsert.c 11 Nov 2006 01:14:18 -0000 1.146
--- src/backend/access/nbtree/nbtinsert.c 27 Nov 2006 14:27:40 -0000
***************
*** 146,151 ****
--- 146,221 ----
}
/*
+ * _bt_suggestblock() -- Find the heap block of the closest index tuple.
+ *
+ * The logic to find the target should match _bt_doinsert, otherwise
+ * we'll be making bad suggestions.
+ */
+ BlockNumber
+ _bt_suggestblock(Relation rel, IndexTuple itup, Relation heapRel)
+ {
+ int natts = rel->rd_rel->relnatts;
+ OffsetNumber offset;
+ Page page;
+ BTPageOpaque opaque;
+
+ ScanKey itup_scankey;
+ BTStack stack;
+ Buffer buf;
+ IndexTuple curitup;
+ BlockNumber suggestion = InvalidBlockNumber;
+
+ /* we need an insertion scan key to do our search, so build one */
+ itup_scankey = _bt_mkscankey(rel, itup);
+
+ /* find the first page containing this key */
+ stack = _bt_search(rel, natts, itup_scankey, false, &buf, BT_READ);
+ if(!BufferIsValid(buf))
+ {
+ /* The index was completely empty. No suggestion then. */
+ return InvalidBlockNumber;
+ }
+ /* we don't need the stack, so free it right away */
+ _bt_freestack(stack);
+
+ page = BufferGetPage(buf);
+ opaque = (BTPageOpaque) PageGetSpecialPointer(page);
+
+ /* Find the location in the page where the new index tuple would go to. */
+
+ offset = _bt_binsrch(rel, buf, natts, itup_scankey, false);
+ if (offset > PageGetMaxOffsetNumber(page))
+ {
+ /* _bt_binsrch returned pointer to end-of-page. It means that
+ * there was no equal items on the page, and the new item should
+ * be inserted as the last tuple of the page. There could be equal
+ * items on the next page, however.
+ *
+ * At the moment, we just ignore the potential equal items on the
+ * right, and pretend there isn't any. We could instead walk right
+ * to the next page to check that, but let's keep it simple for now.
+ */
+ offset = OffsetNumberPrev(offset);
+ }
+ if(offset < P_FIRSTDATAKEY(opaque))
+ {
+ /* We landed on an empty page. We could step left or right until
+ * we find some items, but let's keep it simple for now.
+ */
+ } else {
+ /* We're now positioned at the index tuple that we're interested in. */
+
+ curitup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offset));
+ suggestion = ItemPointerGetBlockNumber(&curitup->t_tid);
+ }
+
+ _bt_relbuf(rel, buf);
+ _bt_freeskey(itup_scankey);
+
+ return suggestion;
+ }
+
+ /*
* _bt_check_unique() -- Check for violation of unique index constraint
*
* Returns InvalidTransactionId if there is no conflict, else an xact ID
Index: src/backend/access/nbtree/nbtree.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/nbtree/nbtree.c,v
retrieving revision 1.153
diff -c -r1.153 nbtree.c
*** src/backend/access/nbtree/nbtree.c 1 Nov 2006 19:43:17 -0000 1.153
--- src/backend/access/nbtree/nbtree.c 27 Nov 2006 14:27:40 -0000
***************
*** 229,234 ****
--- 229,266 ----
}
/*
+ * btsuggestblock() -- find the best place in the heap to put a new tuple.
+ *
+ * This uses the same logic as btinsert to find the place where the index
+ * tuple would go if this was a btinsert call.
+ *
+ * There's room for improvement here. An insert operation will descend
+ * the tree twice, first by btsuggestblock, then by btinsert. Things
+ * might have changed in between, so that the heap tuple is actually
+ * not inserted in the optimal page, but since this is just an
+ * optimization, it's ok if it happens sometimes.
+ */
+ Datum
+ btsuggestblock(PG_FUNCTION_ARGS)
+ {
+ Relation rel = (Relation) PG_GETARG_POINTER(0);
+ Datum *values = (Datum *) PG_GETARG_POINTER(1);
+ bool *isnull = (bool *) PG_GETARG_POINTER(2);
+ Relation heapRel = (Relation) PG_GETARG_POINTER(3);
+ IndexTuple itup;
+ BlockNumber suggestion;
+
+ /* generate an index tuple */
+ itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
+
+ suggestion =_bt_suggestblock(rel, itup, heapRel);
+
+ pfree(itup);
+
+ PG_RETURN_UINT32(suggestion);
+ }
+
+ /*
* btgettuple() -- Get the next tuple in the scan.
*/
Datum
Index: src/backend/executor/execMain.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/executor/execMain.c,v
retrieving revision 1.280
diff -c -r1.280 execMain.c
*** src/backend/executor/execMain.c 4 Oct 2006 00:29:52 -0000 1.280
--- src/backend/executor/execMain.c 27 Nov 2006 17:10:27 -0000
***************
*** 53,58 ****
--- 53,59 ----
#include "utils/lsyscache.h"
#include "utils/memutils.h"
+ bool cluster_inserts = true; /* GUC */
typedef struct evalPlanQual
{
***************
*** 846,851 ****
--- 847,853 ----
resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
resultRelInfo->ri_RelationDesc = resultRelationDesc;
resultRelInfo->ri_NumIndices = 0;
+ resultRelInfo->ri_ClusterIndex = -1;
resultRelInfo->ri_IndexRelationDescs = NULL;
resultRelInfo->ri_IndexRelationInfo = NULL;
/* make a copy so as not to depend on relcache info not changing... */
***************
*** 1330,1335 ****
--- 1332,1338 ----
ResultRelInfo *resultRelInfo;
Relation resultRelationDesc;
Oid newId;
+ BlockNumber suggestedBlock;
/*
* get the heap tuple out of the tuple table slot, making sure we have a
***************
*** 1378,1383 ****
--- 1381,1393 ----
if (resultRelationDesc->rd_att->constr)
ExecConstraints(resultRelInfo, slot, estate);
+ /* Ask the index am of the clustered index for the
+ * best place to put it */
+ if(cluster_inserts)
+ suggestedBlock = ExecSuggestBlock(slot, estate);
+ else
+ suggestedBlock = InvalidBlockNumber;
+
/*
* insert the tuple
*
***************
*** 1386,1392 ****
*/
newId = heap_insert(resultRelationDesc, tuple,
estate->es_snapshot->curcid,
! true, true);
IncrAppended();
(estate->es_processed)++;
--- 1396,1402 ----
*/
newId = heap_insert(resultRelationDesc, tuple,
estate->es_snapshot->curcid,
! true, true, suggestedBlock);
IncrAppended();
(estate->es_processed)++;
***************
*** 2549,2555 ****
tuple,
estate->es_snapshot->curcid,
estate->es_into_relation_use_wal,
! false); /* never any point in using FSM */
/* We know this is a newly created relation, so there are no indexes */
--- 2559,2566 ----
tuple,
estate->es_snapshot->curcid,
estate->es_into_relation_use_wal,
! false, /* never any point in using FSM */
! InvalidBlockNumber);
/* We know this is a newly created relation, so there are no indexes */
Index: src/backend/executor/execUtils.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/executor/execUtils.c,v
retrieving revision 1.140
diff -c -r1.140 execUtils.c
*** src/backend/executor/execUtils.c 4 Oct 2006 00:29:52 -0000 1.140
--- src/backend/executor/execUtils.c 27 Nov 2006 14:27:40 -0000
***************
*** 31,36 ****
--- 31,37 ----
* ExecOpenIndices \
* ExecCloseIndices | referenced by InitPlan, EndPlan,
* ExecInsertIndexTuples / ExecInsert, ExecUpdate
+ * ExecSuggestBlock Referenced by ExecInsert
*
* RegisterExprContextCallback Register function shutdown callback
* UnregisterExprContextCallback Deregister function shutdown callback
***************
*** 874,879 ****
--- 875,881 ----
IndexInfo **indexInfoArray;
resultRelInfo->ri_NumIndices = 0;
+ resultRelInfo->ri_ClusterIndex = -1;
/* fast path if no indexes */
if (!RelationGetForm(resultRelation)->relhasindex)
***************
*** 913,918 ****
--- 915,925 ----
/* extract index key information from the index's pg_index info */
ii = BuildIndexInfo(indexDesc);
+ /* Remember which index is the clustered one.
+ * It's used to call the suggestblock-method on inserts */
+ if(indexDesc->rd_index->indisclustered)
+ resultRelInfo->ri_ClusterIndex = i;
+
relationDescs[i] = indexDesc;
indexInfoArray[i] = ii;
i++;
***************
*** 1062,1067 ****
--- 1069,1137 ----
}
}
+ /* ----------------------------------------------------------------
+ * ExecSuggestBlock
+ *
+ * This routine asks the index am where a new heap tuple
+ * should be placed.
+ * ----------------------------------------------------------------
+ */
+ BlockNumber
+ ExecSuggestBlock(TupleTableSlot *slot,
+ EState *estate)
+ {
+ ResultRelInfo *resultRelInfo;
+ int i;
+ Relation relationDesc;
+ Relation heapRelation;
+ ExprContext *econtext;
+ Datum values[INDEX_MAX_KEYS];
+ bool isnull[INDEX_MAX_KEYS];
+ IndexInfo *indexInfo;
+
+ /*
+ * Get information from the result relation info structure.
+ */
+ resultRelInfo = estate->es_result_relation_info;
+ i = resultRelInfo->ri_ClusterIndex;
+ if(i == -1)
+ return InvalidBlockNumber; /* there was no clustered index */
+
+ heapRelation = resultRelInfo->ri_RelationDesc;
+ relationDesc = resultRelInfo->ri_IndexRelationDescs[i];
+ indexInfo = resultRelInfo->ri_IndexRelationInfo[i];
+
+ /* You can't cluster on a partial index */
+ Assert(indexInfo->ii_Predicate == NIL);
+
+ /*
+ * We will use the EState's per-tuple context for evaluating
+ * index expressions (creating it if it's not already there).
+ */
+ econtext = GetPerTupleExprContext(estate);
+
+ /* Arrange for econtext's scan tuple to be the tuple under test */
+ econtext->ecxt_scantuple = slot;
+
+ /*
+ * FormIndexDatum fills in its values and isnull parameters with the
+ * appropriate values for the column(s) of the index.
+ */
+ FormIndexDatum(indexInfo,
+ slot,
+ estate,
+ values,
+ isnull);
+
+ /*
+ * The index AM does the rest.
+ */
+ return index_suggestblock(relationDesc, /* index relation */
+ values, /* array of index Datums */
+ isnull, /* null flags */
+ heapRelation);
+ }
+
/*
* UpdateChangedParamSet
* Add changed parameters to a plan node's chgParam set
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.358
diff -c -r1.358 guc.c
*** src/backend/utils/misc/guc.c 5 Nov 2006 22:42:09 -0000 1.358
--- src/backend/utils/misc/guc.c 27 Nov 2006 17:08:50 -0000
***************
*** 92,97 ****
--- 92,98 ----
#define MS_PER_D (1000 * 60 * 60 * 24)
/* XXX these should appear in other modules' header files */
+ extern bool cluster_inserts;
extern bool Log_disconnections;
extern int CommitDelay;
extern int CommitSiblings;
***************
*** 402,407 ****
--- 403,416 ----
static struct config_bool ConfigureNamesBool[] =
{
{
+ {"cluster_inserts", PGC_USERSET, DEVELOPER_OPTIONS,
+ gettext_noop("Tries to maintain cluster order on inserts."),
+ NULL
+ },
+ &cluster_inserts,
+ true, NULL, NULL
+ },
+ {
{"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
gettext_noop("Enables the planner's use of sequential-scan plans."),
NULL
Index: src/include/access/genam.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/access/genam.h,v
retrieving revision 1.65
diff -c -r1.65 genam.h
*** src/include/access/genam.h 31 Jul 2006 20:09:05 -0000 1.65
--- src/include/access/genam.h 27 Nov 2006 14:27:40 -0000
***************
*** 93,98 ****
--- 93,101 ----
ItemPointer heap_t_ctid,
Relation heapRelation,
bool check_uniqueness);
+ extern BlockNumber index_suggestblock(Relation indexRelation,
+ Datum *values, bool *isnull,
+ Relation heapRelation);
extern IndexScanDesc index_beginscan(Relation heapRelation,
Relation indexRelation,
***************
*** 123,128 ****
--- 126,133 ----
extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
uint16 procnum);
+ extern Datum dummysuggestblock(PG_FUNCTION_ARGS);
+
/*
* index access method support routines (in genam.c)
*/
Index: src/include/access/heapam.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/access/heapam.h,v
retrieving revision 1.117
diff -c -r1.117 heapam.h
*** src/include/access/heapam.h 5 Nov 2006 22:42:10 -0000 1.117
--- src/include/access/heapam.h 27 Nov 2006 14:27:40 -0000
***************
*** 157,163 ****
extern void setLastTid(const ItemPointer tid);
extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid,
! bool use_wal, bool use_fsm);
extern HTSU_Result heap_delete(Relation relation, ItemPointer tid,
ItemPointer ctid, TransactionId *update_xmax,
CommandId cid, Snapshot crosscheck, bool wait);
--- 157,163 ----
extern void setLastTid(const ItemPointer tid);
extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid,
! bool use_wal, bool use_fsm, BlockNumber suggestedblk);
extern HTSU_Result heap_delete(Relation relation, ItemPointer tid,
ItemPointer ctid, TransactionId *update_xmax,
CommandId cid, Snapshot crosscheck, bool wait);
Index: src/include/access/hio.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/access/hio.h,v
retrieving revision 1.33
diff -c -r1.33 hio.h
*** src/include/access/hio.h 4 Oct 2006 00:30:07 -0000 1.33
--- src/include/access/hio.h 27 Nov 2006 14:27:57 -0000
***************
*** 21,26 ****
extern void RelationPutHeapTuple(Relation relation, Buffer buffer,
HeapTuple tuple);
extern Buffer RelationGetBufferForTuple(Relation relation, Size len,
! Buffer otherBuffer, bool use_fsm);
#endif /* HIO_H */
--- 21,27 ----
extern void RelationPutHeapTuple(Relation relation, Buffer buffer,
HeapTuple tuple);
extern Buffer RelationGetBufferForTuple(Relation relation, Size len,
! Buffer otherBuffer, bool use_fsm,
! BlockNumber suggestedblk);
#endif /* HIO_H */
Index: src/include/access/nbtree.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/access/nbtree.h,v
retrieving revision 1.106
diff -c -r1.106 nbtree.h
*** src/include/access/nbtree.h 1 Nov 2006 19:43:17 -0000 1.106
--- src/include/access/nbtree.h 27 Nov 2006 14:28:23 -0000
***************
*** 479,488 ****
--- 479,491 ----
extern Datum btbulkdelete(PG_FUNCTION_ARGS);
extern Datum btvacuumcleanup(PG_FUNCTION_ARGS);
extern Datum btoptions(PG_FUNCTION_ARGS);
+ extern Datum btsuggestblock(PG_FUNCTION_ARGS);
/*
* prototypes for functions in nbtinsert.c
*/
+ extern BlockNumber _bt_suggestblock(Relation rel, IndexTuple itup,
+ Relation heapRel);
extern void _bt_doinsert(Relation rel, IndexTuple itup,
bool index_is_unique, Relation heapRel);
extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, int access);
Index: src/include/catalog/pg_am.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/catalog/pg_am.h,v
retrieving revision 1.46
diff -c -r1.46 pg_am.h
*** src/include/catalog/pg_am.h 31 Jul 2006 20:09:05 -0000 1.46
--- src/include/catalog/pg_am.h 27 Nov 2006 14:27:40 -0000
***************
*** 65,70 ****
--- 65,71 ----
regproc amvacuumcleanup; /* post-VACUUM cleanup function */
regproc amcostestimate; /* estimate cost of an indexscan */
regproc amoptions; /* parse AM-specific parameters */
+ regproc amsuggestblock; /* suggest a block where to put heap tuple */
} FormData_pg_am;
/* ----------------
***************
*** 78,84 ****
* compiler constants for pg_am
* ----------------
*/
! #define Natts_pg_am 23
#define Anum_pg_am_amname 1
#define Anum_pg_am_amstrategies 2
#define Anum_pg_am_amsupport 3
--- 79,85 ----
* compiler constants for pg_am
* ----------------
*/
! #define Natts_pg_am 24
#define Anum_pg_am_amname 1
#define Anum_pg_am_amstrategies 2
#define Anum_pg_am_amsupport 3
***************
*** 102,123 ****
#define Anum_pg_am_amvacuumcleanup 21
#define Anum_pg_am_amcostestimate 22
#define Anum_pg_am_amoptions 23
/* ----------------
* initial contents of pg_am
* ----------------
*/
! DATA(insert OID = 403 ( btree 5 1 1 t t t t f t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate btoptions ));
DESCR("b-tree index access method");
#define BTREE_AM_OID 403
! DATA(insert OID = 405 ( hash 1 1 0 f f f f f f hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions ));
DESCR("hash index access method");
#define HASH_AM_OID 405
! DATA(insert OID = 783 ( gist 100 7 0 f t t t t t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions ));
DESCR("GiST index access method");
#define GIST_AM_OID 783
! DATA(insert OID = 2742 ( gin 100 4 0 f f f f t f gininsert ginbeginscan gingettuple gingetmulti ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ginoptions ));
DESCR("GIN index access method");
#define GIN_AM_OID 2742
--- 103,125 ----
#define Anum_pg_am_amvacuumcleanup 21
#define Anum_pg_am_amcostestimate 22
#define Anum_pg_am_amoptions 23
+ #define Anum_pg_am_amsuggestblock 24
/* ----------------
* initial contents of pg_am
* ----------------
*/
! DATA(insert OID = 403 ( btree 5 1 1 t t t t f t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate btoptions btsuggestblock));
DESCR("b-tree index access method");
#define BTREE_AM_OID 403
! DATA(insert OID = 405 ( hash 1 1 0 f f f f f f hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions dummysuggestblock));
DESCR("hash index access method");
#define HASH_AM_OID 405
! DATA(insert OID = 783 ( gist 100 7 0 f t t t t t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions dummysuggestblock));
DESCR("GiST index access method");
#define GIST_AM_OID 783
! DATA(insert OID = 2742 ( gin 100 4 0 f f f f t f gininsert ginbeginscan gingettuple gingetmulti ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ginoptions dummysuggestblock ));
DESCR("GIN index access method");
#define GIN_AM_OID 2742
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.427
diff -c -r1.427 pg_proc.h
*** src/include/catalog/pg_proc.h 4 Oct 2006 00:30:07 -0000 1.427
--- src/include/catalog/pg_proc.h 27 Nov 2006 14:27:40 -0000
***************
*** 682,687 ****
--- 682,689 ----
DESCR("btree(internal)");
DATA(insert OID = 2785 ( btoptions PGNSP PGUID 12 f f t f s 2 17 "1009 16" _null_ _null_ _null_ btoptions - _null_ ));
DESCR("btree(internal)");
+ DATA(insert OID = 2858 ( btsuggestblock PGNSP PGUID 12 f f t f v 4 23 "2281 2281 2281 2281" _null_ _null_ _null_ btsuggestblock - _null_ ));
+ DESCR("btree(internal)");
DATA(insert OID = 339 ( poly_same PGNSP PGUID 12 f f t f i 2 16 "604 604" _null_ _null_ _null_ poly_same - _null_ ));
DESCR("same as?");
***************
*** 3974,3979 ****
--- 3976,3984 ----
DATA(insert OID = 2892 ( pg_advisory_unlock_all PGNSP PGUID 12 f f t f v 0 2278 "" _null_ _null_ _null_ pg_advisory_unlock_all - _null_ ));
DESCR("release all advisory locks");
+ DATA(insert OID = 2857 ( dummysuggestblock PGNSP PGUID 12 f f t f v 4 23 "2281 2281 2281 2281" _null_ _null_ _null_ dummysuggestblock - _null_ ));
+ DESCR("dummy amsuggestblock implementation (internal)");
+
/*
* Symbolic values for provolatile column: these indicate whether the result
* of a function is dependent *only* on the values of its explicit arguments,
Index: src/include/executor/executor.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/executor/executor.h,v
retrieving revision 1.130
diff -c -r1.130 executor.h
*** src/include/executor/executor.h 4 Oct 2006 00:30:08 -0000 1.130
--- src/include/executor/executor.h 27 Nov 2006 14:27:40 -0000
***************
*** 272,277 ****
--- 272,278 ----
extern void ExecCloseIndices(ResultRelInfo *resultRelInfo);
extern void ExecInsertIndexTuples(TupleTableSlot *slot, ItemPointer tupleid,
EState *estate, bool is_vacuum);
+ extern BlockNumber ExecSuggestBlock(TupleTableSlot *slot, EState *estate);
extern void RegisterExprContextCallback(ExprContext *econtext,
ExprContextCallbackFunction function,
Index: src/include/nodes/execnodes.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/nodes/execnodes.h,v
retrieving revision 1.161
diff -c -r1.161 execnodes.h
*** src/include/nodes/execnodes.h 28 Sep 2006 20:51:42 -0000 1.161
--- src/include/nodes/execnodes.h 27 Nov 2006 14:27:40 -0000
***************
*** 259,264 ****
--- 259,266 ----
* NumIndices # of indices existing on result relation
* IndexRelationDescs array of relation descriptors for indices
* IndexRelationInfo array of key/attr info for indices
+ * ClusterIndex index to the IndexRelationInfo array of the
+ * clustered index, or -1 if there's none
* TrigDesc triggers to be fired, if any
* TrigFunctions cached lookup info for trigger functions
* TrigInstrument optional runtime measurements for triggers
***************
*** 275,280 ****
--- 277,283 ----
int ri_NumIndices;
RelationPtr ri_IndexRelationDescs;
IndexInfo **ri_IndexRelationInfo;
+ int ri_ClusterIndex;
TriggerDesc *ri_TrigDesc;
FmgrInfo *ri_TrigFunctions;
struct Instrumentation *ri_TrigInstrument;
Index: src/include/utils/rel.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/utils/rel.h,v
retrieving revision 1.92
diff -c -r1.92 rel.h
*** src/include/utils/rel.h 4 Oct 2006 00:30:10 -0000 1.92
--- src/include/utils/rel.h 27 Nov 2006 14:27:40 -0000
***************
*** 116,121 ****
--- 116,122 ----
FmgrInfo amvacuumcleanup;
FmgrInfo amcostestimate;
FmgrInfo amoptions;
+ FmgrInfo amsuggestblock;
} RelationAmInfo;