+ if ( gvs->callback(items+i, gvs->callback_state) ) {
+ gvs->result->tuples_removed += 1;
+ if ( !*cleaned ) {
+ *cleaned = (ItemPointerData*)palloc(sizeof(ItemPointerData)*nitem);
+ if ( i!=0 )
+ memcpy( *cleaned, items, sizeof(ItemPointerData)*i);
+ }
+ } else {
+ gvs->result->num_index_tuples += 1;
+ if (i!=j)
+ (*cleaned)[j] = items[i];
+ j++;
+ }
+ }
+
+ return j;
+}
+
+/*
+ * fills WAL record for vacuum leaf page
+ */
+static void
+xlogVacuumPage(Relation index, Buffer buffer) {
+ Page page = BufferGetPage( buffer );
+ XLogRecPtr recptr;
+ XLogRecData rdata[3];
+ ginxlogVacuumPage data;
+ char *backup;
+ char itups[BLCKSZ];
+ uint32 len=0;
+
+ Assert( GinPageIsLeaf( page ) );
+
+ if (index->rd_istemp)
+ return;
+
+ data.node = index->rd_node;
+ data.blkno = BufferGetBlockNumber(buffer);
+
+ if ( GinPageIsData( page ) ) {
+ backup = GinDataPageGetData( page );
+ data.nitem = GinPageGetOpaque( page )->maxoff;
+ if ( data.nitem )
+ len = MAXALIGN( sizeof(ItemPointerData)*data.nitem );
+ } else {
+ char *ptr;
+ OffsetNumber i;
+
+ ptr = backup = itups;
+ for(i=FirstOffsetNumber;i<=PageGetMaxOffsetNumber(page);i++) {
+ IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));
+ memcpy( ptr, itup, IndexTupleSize( itup ) );
+ ptr += MAXALIGN( IndexTupleSize( itup ) );
+ }
+
+ data.nitem = PageGetMaxOffsetNumber(page);
+ len = ptr-backup;
+ }
+
+ rdata[0].buffer = buffer;
+ rdata[0].buffer_std = ( GinPageIsData( page ) ) ? FALSE : TRUE;
+ rdata[0].len = 0;
+ rdata[0].data = NULL;
+ rdata[0].next = rdata + 1;
+
+ rdata[1].buffer = InvalidBuffer;
+ rdata[1].len = sizeof(ginxlogVacuumPage);
+ rdata[1].data = (char*)&data;
+
+ if ( len == 0 ) {
+ rdata[1].next = NULL;
+ } else {
+ rdata[1].next = rdata + 2;
+
+ rdata[2].buffer = InvalidBuffer;
+ rdata[2].len = len;
+ rdata[2].data = backup;
+ rdata[2].next = NULL;
+ }
+
+ recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_VACUUM_PAGE, rdata);
+ PageSetLSN(page, recptr);
+ PageSetTLI(page, ThisTimeLineID);
+}
+
+static bool
+ginVacuumPostingTreeLeaves( GinVacuumState *gvs, BlockNumber blkno, bool isRoot, Buffer *rootBuffer ) {
+ Buffer buffer = ReadBuffer( gvs->index, blkno );
+ Page page = BufferGetPage( buffer );
+ bool hasVoidPage = FALSE;
+
+ /*
+ * We should be sure that we don't concurrent with inserts, insert process
+ * never release root page until end (but it can unlock it and lock again).
+ * If we lock root with with LockBufferForCleanup, new scan process can't begin,
+ * but previous may run.
+ * ginmarkpos/start* keeps buffer pinned, so we will wait for it.
+ * We lock only one posting tree in whole index, so, it's concurrent enough..
+ * Side effect: after this is full complete, tree is unused by any other process
+ */
+
+ LockBufferForCleanup( buffer );
+
+ Assert( GinPageIsData(page) );
+
+ if ( GinPageIsLeaf(page) ) {
+ OffsetNumber newMaxOff, oldMaxOff = GinPageGetOpaque(page)->maxoff;
+ ItemPointerData *cleaned = NULL;
+
+ newMaxOff = ginVacuumPostingList( gvs,
+ (ItemPointer)GinDataPageGetData(page), oldMaxOff, &cleaned );
+
+ /* saves changes about deleted tuple ... */
+ if ( oldMaxOff != newMaxOff ) {
+
+ START_CRIT_SECTION();
+
+ if ( newMaxOff > 0 )
+ memcpy( GinDataPageGetData(page), cleaned, sizeof(ItemPointerData) * newMaxOff );
+ pfree( cleaned );
+ GinPageGetOpaque(page)->maxoff = newMaxOff;
+
+ xlogVacuumPage(gvs->index, buffer);
+
+ MarkBufferDirty( buffer );
+ END_CRIT_SECTION();
+
+ /* if root is a leaf page, we don't desire futher processing */
+ if ( !isRoot && GinPageGetOpaque(page)->maxoff < FirstOffsetNumber )
+ hasVoidPage = TRUE;
+ }
+ } else {
+ OffsetNumber i;
+ bool isChildHasVoid = FALSE;
+
+ for( i=FirstOffsetNumber ; i <= GinPageGetOpaque(page)->maxoff ; i++ ) {
+ PostingItem *pitem = (PostingItem*)GinDataPageGetItem(page, i);
+ if ( ginVacuumPostingTreeLeaves( gvs, PostingItemGetBlockNumber(pitem), FALSE, NULL ) )
+ isChildHasVoid = TRUE;
+ }
+
+ if ( isChildHasVoid )
+ hasVoidPage = TRUE;
+ }
+
+ /* if we have root and theres void pages in tree, then we don't release lock
+ to go further processing and guarantee that tree is unused */
+ if ( !(isRoot && hasVoidPage) ) {
+ UnlockReleaseBuffer( buffer );
+ } else {
+ Assert( rootBuffer );
+ *rootBuffer = buffer;
+ }
+
+ return hasVoidPage;
+}
+
+static void
+ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkno,
+ BlockNumber parentBlkno, OffsetNumber myoff, bool isParentRoot ) {
+ Buffer dBuffer = ReadBuffer( gvs->index, deleteBlkno );
+ Buffer lBuffer = (leftBlkno==InvalidBlockNumber) ? InvalidBuffer : ReadBuffer( gvs->index, leftBlkno );
+ Buffer pBuffer = ReadBuffer( gvs->index, parentBlkno );
+ Page page, parentPage;
+
+ LockBuffer( dBuffer, GIN_EXCLUSIVE );
+ if ( !isParentRoot ) /* parent is already locked by LockBufferForCleanup() */
+ LockBuffer( pBuffer, GIN_EXCLUSIVE );
+
+ START_CRIT_SECTION();
+
+ if ( leftBlkno!= InvalidBlockNumber ) {
+ BlockNumber rightlink;
+
+ LockBuffer( lBuffer, GIN_EXCLUSIVE );
+
+ page = BufferGetPage( dBuffer );
+ rightlink = GinPageGetOpaque(page)->rightlink;
+
+ page = BufferGetPage( lBuffer );
+ GinPageGetOpaque(page)->rightlink = rightlink;
+ }
+
+ parentPage = BufferGetPage( pBuffer );
+ PageDeletePostingItem(parentPage, myoff);
+
+ page = BufferGetPage( dBuffer );
+ GinPageGetOpaque(page)->flags = GIN_DELETED;
+
+ if (!gvs->index->rd_istemp) {
+ XLogRecPtr recptr;
+ XLogRecData rdata[4];
+ ginxlogDeletePage data;
+ int n;
+
+ data.node = gvs->index->rd_node;
+ data.blkno = deleteBlkno;
+ data.parentBlkno = parentBlkno;
+ data.parentOffset = myoff;
+ data.leftBlkno = leftBlkno;
+ data.rightLink = GinPageGetOpaque(page)->rightlink;
+
+ rdata[0].buffer = dBuffer;
+ rdata[0].buffer_std = FALSE;
+ rdata[0].data = NULL;
+ rdata[0].len = 0;
+ rdata[0].next = rdata + 1;
+
+ rdata[1].buffer = pBuffer;
+ rdata[1].buffer_std = FALSE;
+ rdata[1].data = NULL;
+ rdata[1].len = 0;
+ rdata[1].next = rdata + 2;
+
+ if ( leftBlkno!= InvalidBlockNumber ) {
+ rdata[2].buffer = lBuffer;
+ rdata[2].buffer_std = FALSE;
+ rdata[2].data = NULL;
+ rdata[2].len = 0;
+ rdata[2].next = rdata + 3;
+ n = 3;
+ } else
+ n = 2;
+
+ rdata[n].buffer = InvalidBuffer;
+ rdata[n].buffer_std = FALSE;
+ rdata[n].len = sizeof(ginxlogDeletePage);
+ rdata[n].data = (char*)&data;
+ rdata[n].next = NULL;
+
+ recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_DELETE_PAGE, rdata);
+ PageSetLSN(page, recptr);
+ PageSetTLI(page, ThisTimeLineID);
+ PageSetLSN(parentPage, recptr);
+ PageSetTLI(parentPage, ThisTimeLineID);
+ if ( leftBlkno!= InvalidBlockNumber ) {
+ page = BufferGetPage( lBuffer );
+ PageSetLSN(page, recptr);
+ PageSetTLI(page, ThisTimeLineID);
+ }
+ }
+
+ MarkBufferDirty( pBuffer );
+ if ( !isParentRoot )
+ LockBuffer( pBuffer, GIN_UNLOCK );
+ ReleaseBuffer( pBuffer );
+
+ if ( leftBlkno!= InvalidBlockNumber ) {
+ MarkBufferDirty( lBuffer );
+ UnlockReleaseBuffer( lBuffer );
+ }
+
+ MarkBufferDirty( dBuffer );
+ UnlockReleaseBuffer( dBuffer );
+
+ END_CRIT_SECTION();
+
+ gvs->result->pages_deleted++;
+}
+
+typedef struct DataPageDeleteStack {
+ struct DataPageDeleteStack *child;
+ struct DataPageDeleteStack *parent;
+
+ BlockNumber blkno;
+ bool isRoot;
+} DataPageDeleteStack;
+
+/*
+ * scans posting tree and deletes empty pages
+ */
+static bool
+ginScanToDelete( GinVacuumState *gvs, BlockNumber blkno, bool isRoot, DataPageDeleteStack *parent, OffsetNumber myoff ) {
+ DataPageDeleteStack *me;
+ Buffer buffer;
+ Page page;
+ bool meDelete = FALSE;
+
+ if ( isRoot ) {
+ me = parent;
+ } else {
+ if ( ! parent->child ) {
+ me = (DataPageDeleteStack*)palloc0(sizeof(DataPageDeleteStack));
+ me->parent=parent;
+ parent->child = me;
+ me->blkno = InvalidBlockNumber;
+ } else
+ me = parent->child;
+ }
+
+ buffer = ReadBuffer( gvs->index, blkno );
+ page = BufferGetPage( buffer );
+
+ Assert( GinPageIsData(page) );
+
+ if ( !GinPageIsLeaf(page) ) {
+ OffsetNumber i;
+
+ for(i=FirstOffsetNumber;i<=GinPageGetOpaque(page)->maxoff;i++) {
+ PostingItem *pitem = (PostingItem*)GinDataPageGetItem(page, i);
+
+ if ( ginScanToDelete( gvs, PostingItemGetBlockNumber(pitem), FALSE, me, i ) )
+ i--;
+ }
+ }
+
+ if ( GinPageGetOpaque(page)->maxoff < FirstOffsetNumber ) {
+ if ( !( me->blkno == InvalidBlockNumber && GinPageRightMost(page) ) ) {
+ /* we never delete right most branch */
+ Assert( !isRoot );
+ if ( GinPageGetOpaque(page)->maxoff < FirstOffsetNumber ) {
+ ginDeletePage( gvs, blkno, me->blkno, me->parent->blkno, myoff, me->parent->isRoot );
+ meDelete = TRUE;
+ }
+ }
+ }
+
+ ReleaseBuffer( buffer );
+
+ if ( !meDelete )
+ me->blkno = blkno;
+
+ return meDelete;
+}
+
+static void
+ginVacuumPostingTree( GinVacuumState *gvs, BlockNumber rootBlkno ) {
+ Buffer rootBuffer = InvalidBuffer;
+ DataPageDeleteStack root, *ptr, *tmp;
+
+ if ( ginVacuumPostingTreeLeaves(gvs, rootBlkno, TRUE, &rootBuffer)==FALSE ) {
+ Assert( rootBuffer == InvalidBuffer );
+ return;
+ }
+
+ memset(&root,0,sizeof(DataPageDeleteStack));
+ root.blkno = rootBlkno;
+ root.isRoot = TRUE;
+
+ vacuum_delay_point();
+
+ ginScanToDelete( gvs, rootBlkno, TRUE, &root, InvalidOffsetNumber );
+
+ ptr = root.child;
+ while( ptr ) {
+ tmp = ptr->child;
+ pfree( ptr );
+ ptr = tmp;
+ }
+
+ UnlockReleaseBuffer( rootBuffer );
+}
+
+/*
+ * returns modified page or NULL if page isn't modified.
+ * Function works with original page until first change is occured,
+ * then page is copied into temprorary one.
+ */
+static Page
+ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint32 *nroot) {
+ Page origpage = BufferGetPage( buffer ), tmppage;
+ OffsetNumber i, maxoff = PageGetMaxOffsetNumber( origpage );
+
+ tmppage = origpage;
+
+ *nroot=0;
+
+ for(i=FirstOffsetNumber; i<= maxoff; i++) {
+ IndexTuple itup = (IndexTuple) PageGetItem(tmppage, PageGetItemId(tmppage, i));
+
+ if ( GinIsPostingTree(itup) ) {
+ /* store posting tree's roots for further processing,
+ we can't vacuum it just now due to risk of deadlocks with scans/inserts */
+ roots[ *nroot ] = GinItemPointerGetBlockNumber(&itup->t_tid);
+ (*nroot)++;
+ } else if ( GinGetNPosting(itup) > 0 ) {
+ /* if we already create temrorary page, we will make changes in place */
+ ItemPointerData *cleaned = (tmppage==origpage) ? NULL : GinGetPosting(itup );
+ uint32 newN = ginVacuumPostingList( gvs, GinGetPosting(itup), GinGetNPosting(itup), &cleaned );
+
+ if ( GinGetNPosting(itup) != newN ) {
+ bool isnull;
+ Datum value;
+
+ /*
+ * Some ItemPointers was deleted, so we should remake our tuple
+ */
+
+ if ( tmppage==origpage ) {
+ /*
+ * On first difference we create temprorary page in memory
+ * and copies content in to it.
+ */
+ tmppage=GinPageGetCopyPage ( origpage );
+
+ if ( newN > 0 ) {
+ Size pos = ((char*)GinGetPosting(itup)) - ((char*)origpage);
+ memcpy( tmppage+pos, cleaned, sizeof(ItemPointerData)*newN );
+ }
+
+ pfree( cleaned );
+
+ /* set itup pointer to new page */
+ itup = (IndexTuple) PageGetItem(tmppage, PageGetItemId(tmppage, i));
+ }
+
+ value = index_getattr(itup, FirstOffsetNumber, gvs->ginstate.tupdesc, &isnull);
+ itup = GinFormTuple(&gvs->ginstate, value, GinGetPosting(itup), newN);
+ PageIndexTupleDelete(tmppage, i);
+
+ if ( PageAddItem( tmppage, (Item)itup, IndexTupleSize(itup), i, LP_USED ) != i )
+ elog(ERROR, "failed to add item to index page in \"%s\"",
+ RelationGetRelationName(gvs->index));
+
+ pfree( itup );
+ }
+ }
+ }
+
+ return ( tmppage==origpage ) ? NULL : tmppage;
+}
+
+Datum
+ginbulkdelete(PG_FUNCTION_ARGS) {
+ Relation index = (Relation) PG_GETARG_POINTER(0);
+ IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
+ void *callback_state = (void *) PG_GETARG_POINTER(2);
+ BlockNumber blkno = GIN_ROOT_BLKNO;
+ GinVacuumState gvs;
+ Buffer buffer;
+ BlockNumber rootOfPostingTree[ BLCKSZ/ (sizeof(IndexTupleData)+sizeof(ItemId)) ];
+ uint32 nRoot;
+
+ gvs.index = index;
+ gvs.result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
+ gvs.callback = callback;
+ gvs.callback_state = callback_state;
+ initGinState(&gvs.ginstate, index);
+
+ buffer = ReadBuffer( index, blkno );
+
+ /* find leaf page */
+ for(;;) {
+ Page page = BufferGetPage( buffer );
+ IndexTuple itup;
+
+ LockBuffer(buffer,GIN_SHARE);
+
+ Assert( !GinPageIsData(page) );
+
+ if ( GinPageIsLeaf(page) ) {
+ LockBuffer(buffer,GIN_UNLOCK);
+ LockBuffer(buffer,GIN_EXCLUSIVE);
+
+ if ( blkno==GIN_ROOT_BLKNO && !GinPageIsLeaf(page) ) {
+ LockBuffer(buffer,GIN_UNLOCK);
+ continue; /* check it one more */
+ }
+ break;
+ }
+
+ Assert( PageGetMaxOffsetNumber(page) >= FirstOffsetNumber );
+
+ itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, FirstOffsetNumber));
+ blkno = GinItemPointerGetBlockNumber(&(itup)->t_tid);
+ Assert( blkno!= InvalidBlockNumber );
+
+ LockBuffer(buffer,GIN_UNLOCK);
+ buffer = ReleaseAndReadBuffer( buffer, index, blkno );
+ }
+
+ /* right now we found leftmost page in entry's BTree */
+
+ for(;;) {
+ Page page = BufferGetPage( buffer );
+ Page resPage;
+ uint32 i;
+
+ Assert( !GinPageIsData(page) );
+
+ resPage = ginVacuumEntryPage(&gvs, buffer, rootOfPostingTree, &nRoot);
+
+ blkno = GinPageGetOpaque( page )->rightlink;
+
+ if ( resPage ) {
+ START_CRIT_SECTION();
+ PageRestoreTempPage( resPage, page );
+ xlogVacuumPage(gvs.index, buffer);
+ MarkBufferDirty( buffer );
+ UnlockReleaseBuffer(buffer);
+ END_CRIT_SECTION();
+ } else {
+ UnlockReleaseBuffer(buffer);
+ }
+
+ vacuum_delay_point();
+
+ for(i=0; i
+ ginVacuumPostingTree( &gvs, rootOfPostingTree[i] );
+ vacuum_delay_point();
+ }
+
+ if ( blkno==InvalidBlockNumber ) /*rightmost page*/
+ break;
+
+ buffer = ReadBuffer( index, blkno );
+ LockBuffer(buffer,GIN_EXCLUSIVE);
+ }
+
+ PG_RETURN_POINTER(gvs.result);
+}
+
+Datum
+ginvacuumcleanup(PG_FUNCTION_ARGS) {
+ Relation index = (Relation) PG_GETARG_POINTER(0);
+ IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
+ IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);
+ bool needLock = !RELATION_IS_LOCAL(index);
+ BlockNumber npages,
+ blkno;
+ BlockNumber nFreePages,
+ *freePages,
+ maxFreePages;
+ BlockNumber lastBlock = GIN_ROOT_BLKNO,
+ lastFilledBlock = GIN_ROOT_BLKNO;
+
+
+ if (info->vacuum_full) {
+ LockRelation(index, AccessExclusiveLock);
+ needLock = false;
+ }
+
+ if (needLock)
+ LockRelationForExtension(index, ExclusiveLock);
+ npages = RelationGetNumberOfBlocks(index);
+ if (needLock)
+ UnlockRelationForExtension(index, ExclusiveLock);
+
+ maxFreePages = npages;
+ if (maxFreePages > MaxFSMPages)
+ maxFreePages = MaxFSMPages;
+
+ nFreePages = 0;
+ freePages = (BlockNumber *) palloc(sizeof(BlockNumber) * maxFreePages);
+
+ for (blkno = GIN_ROOT_BLKNO + 1; blkno < npages; blkno++) {
+ Buffer buffer;
+ Page page;
+
+ vacuum_delay_point();
+
+ buffer = ReadBuffer(index, blkno);
+ LockBuffer(buffer, GIN_SHARE);
+ page = (Page) BufferGetPage(buffer);
+
+ if ( GinPageIsDeleted(page) ) {
+ if (nFreePages < maxFreePages)
+ freePages[nFreePages++] = blkno;
+ } else
+ lastFilledBlock = blkno;
+
+ UnlockReleaseBuffer(buffer);
+ }
+ lastBlock = npages - 1;
+
+ if (info->vacuum_full && nFreePages > 0) {
+ /* try to truncate index */
+ int i;
+ for (i = 0; i < nFreePages; i++)
+ if (freePages[i] >= lastFilledBlock) {
+ nFreePages = i;
+ break;
+ }
+
+ if (lastBlock > lastFilledBlock)
+ RelationTruncate(index, lastFilledBlock + 1);
+
+ stats->pages_removed = lastBlock - lastFilledBlock;
+ }
+
+ RecordIndexFreeSpace(&index->rd_node, nFreePages, freePages);
+ stats->pages_free = nFreePages;
+
+ if (needLock)
+ LockRelationForExtension(index, ExclusiveLock);
+ stats->num_pages = RelationGetNumberOfBlocks(index);
+ if (needLock)
+ UnlockRelationForExtension(index, ExclusiveLock);
+
+ if (info->vacuum_full)
+ UnlockRelation(index, AccessExclusiveLock);
+
+ PG_RETURN_POINTER(stats);
+}
+
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * ginxlog.c
+ * WAL replay logic for inverted index.
+ *
+ *
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginxlog.c,v 1.1 2006/05/02 11:28:54 teodor Exp $
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/gin.h"
+#include "access/heapam.h"
+#include "catalog/index.h"
+#include "commands/vacuum.h"
+#include "miscadmin.h"
+#include "utils/memutils.h"
+
+static MemoryContext opCtx; /* working memory for operations */
+static MemoryContext topCtx;
+
+typedef struct ginIncompleteSplit {
+ RelFileNode node;
+ BlockNumber leftBlkno;
+ BlockNumber rightBlkno;
+ BlockNumber rootBlkno;
+} ginIncompleteSplit;
+
+static List *incomplete_splits;
+
+static void
+pushIncompleteSplit(RelFileNode node, BlockNumber leftBlkno, BlockNumber rightBlkno, BlockNumber rootBlkno) {
+ ginIncompleteSplit *split;
+
+ MemoryContextSwitchTo( topCtx );
+
+ split = palloc(sizeof(ginIncompleteSplit));
+
+ split->node = node;
+ split->leftBlkno = leftBlkno;
+ split->rightBlkno = rightBlkno;
+ split->rootBlkno = rootBlkno;
+
+ incomplete_splits = lappend(incomplete_splits, split);
+
+ MemoryContextSwitchTo( opCtx );
+}
+
+static void
+forgetIncompleteSplit(RelFileNode node, BlockNumber leftBlkno, BlockNumber updateBlkno) {
+ ListCell *l;
+
+ foreach(l, incomplete_splits) {
+ ginIncompleteSplit *split = (ginIncompleteSplit *) lfirst(l);
+
+ if ( RelFileNodeEquals(node, split->node) && leftBlkno == split->leftBlkno && updateBlkno == split->rightBlkno ) {
+ incomplete_splits = list_delete_ptr(incomplete_splits, split);
+ break;
+ }
+ }
+}
+
+static void
+ginRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record) {
+ RelFileNode *node = (RelFileNode *) XLogRecGetData(record);
+ Relation reln;
+ Buffer buffer;
+ Page page;
+
+ reln = XLogOpenRelation(*node);
+ buffer = XLogReadBuffer(reln, GIN_ROOT_BLKNO, true);
+ Assert(BufferIsValid(buffer));
+ page = (Page) BufferGetPage(buffer);
+
+ GinInitBuffer(buffer, GIN_LEAF);
+
+ PageSetLSN(page, lsn);
+ PageSetTLI(page, ThisTimeLineID);
+
+ MarkBufferDirty(buffer);
+ UnlockReleaseBuffer(buffer);
+}
+
+static void
+ginRedoCreatePTree(XLogRecPtr lsn, XLogRecord *record) {
+ ginxlogCreatePostingTree *data = (ginxlogCreatePostingTree*)XLogRecGetData(record);
+ ItemPointerData *items = (ItemPointerData*)(XLogRecGetData(record) + sizeof(ginxlogCreatePostingTree));
+ Relation reln;
+ Buffer buffer;
+ Page page;
+
+ reln = XLogOpenRelation(data->node);
+ buffer = XLogReadBuffer(reln, data->blkno, true);
+ Assert(BufferIsValid(buffer));
+ page = (Page) BufferGetPage(buffer);
+
+ GinInitBuffer(buffer, GIN_DATA|GIN_LEAF);
+ memcpy( GinDataPageGetData(page), items, sizeof(ItemPointerData) * data->nitem );
+ GinPageGetOpaque(page)->maxoff = data->nitem;
+
+ PageSetLSN(page, lsn);
+ PageSetTLI(page, ThisTimeLineID);
+
+ MarkBufferDirty(buffer);
+ UnlockReleaseBuffer(buffer);
+}
+
+static void
+ginRedoInsert(XLogRecPtr lsn, XLogRecord *record) {
+ ginxlogInsert *data = (ginxlogInsert*)XLogRecGetData(record);
+ Relation reln;
+ Buffer buffer;
+ Page page;
+
+ /* nothing else to do if page was backed up (and no info to do it with) */
+ if (record->xl_info & XLR_BKP_BLOCK_1)
+ return;
+
+ reln = XLogOpenRelation(data->node);
+ buffer = XLogReadBuffer(reln, data->blkno, false);
+ Assert(BufferIsValid(buffer));
+ page = (Page) BufferGetPage(buffer);
+
+ if ( data->isData ) {
+ Assert( data->isDelete == FALSE );
+ Assert( GinPageIsData( page ) );
+
+ if ( data->isLeaf ) {
+ OffsetNumber i;
+ ItemPointerData *items = (ItemPointerData*)( XLogRecGetData(record) + sizeof(ginxlogInsert) );
+
+ Assert( GinPageIsLeaf( page ) );
+ Assert( data->updateBlkno == InvalidBlockNumber );
+
+ for(i=0;initem;i++)
+ GinDataPageAddItem( page, items+i, data->offset + i );
+ } else {
+ PostingItem *pitem;
+
+ Assert( !GinPageIsLeaf( page ) );
+
+ if ( data->updateBlkno != InvalidBlockNumber ) {
+ /* update link to right page after split */
+ pitem = (PostingItem*)GinDataPageGetItem(page, data->offset);
+ PostingItemSetBlockNumber( pitem, data->updateBlkno );
+ }
+
+ pitem = (PostingItem*)( XLogRecGetData(record) + sizeof(ginxlogInsert) );
+
+ GinDataPageAddItem( page, pitem, data->offset );
+
+ if ( data->updateBlkno != InvalidBlockNumber )
+ forgetIncompleteSplit(data->node, PostingItemGetBlockNumber( pitem ), data->updateBlkno);
+ }
+ } else {
+ IndexTuple itup;
+
+ Assert( !GinPageIsData( page ) );
+
+ if ( data->updateBlkno != InvalidBlockNumber ) {
+ /* update link to right page after split */
+ Assert( !GinPageIsLeaf( page ) );
+ Assert( data->offset>=FirstOffsetNumber && data->offset<=PageGetMaxOffsetNumber(page) );
+ itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, data->offset));
+ ItemPointerSet(&itup->t_tid, data->updateBlkno, InvalidOffsetNumber);
+ }
+
+ if ( data->isDelete ) {
+ Assert( GinPageIsLeaf( page ) );
+ Assert( data->offset>=FirstOffsetNumber && data->offset<=PageGetMaxOffsetNumber(page) );
+ PageIndexTupleDelete(page, data->offset);
+ }
+
+ itup = (IndexTuple)( XLogRecGetData(record) + sizeof(ginxlogInsert) );
+
+ if ( PageAddItem( page, (Item)itup, IndexTupleSize(itup), data->offset, LP_USED) == InvalidOffsetNumber )
+ elog(ERROR, "failed to add item to index page in %u/%u/%u",
+ data->node.spcNode, data->node.dbNode, data->node.relNode );
+
+ if ( !data->isLeaf && data->updateBlkno != InvalidBlockNumber )
+ forgetIncompleteSplit(data->node, GinItemPointerGetBlockNumber( &itup->t_tid ), data->updateBlkno);
+ }
+
+ PageSetLSN(page, lsn);
+ PageSetTLI(page, ThisTimeLineID);
+
+ MarkBufferDirty(buffer);
+ UnlockReleaseBuffer(buffer);
+}
+
+static void
+ginRedoSplit(XLogRecPtr lsn, XLogRecord *record) {
+ ginxlogSplit *data = (ginxlogSplit*)XLogRecGetData(record);
+ Relation reln;
+ Buffer lbuffer, rbuffer;
+ Page lpage, rpage;
+ uint32 flags = 0;
+
+ reln = XLogOpenRelation(data->node);
+
+ if ( data->isLeaf )
+ flags |= GIN_LEAF;
+ if ( data->isData )
+ flags |= GIN_DATA;
+
+ lbuffer = XLogReadBuffer(reln, data->lblkno, data->isRootSplit);
+ Assert(BufferIsValid(lbuffer));
+ lpage = (Page) BufferGetPage(lbuffer);
+ GinInitBuffer(lbuffer, flags);
+
+ rbuffer = XLogReadBuffer(reln, data->rblkno, true);
+ Assert(BufferIsValid(rbuffer));
+ rpage = (Page) BufferGetPage(rbuffer);
+ GinInitBuffer(rbuffer, flags);
+
+ GinPageGetOpaque(lpage)->rightlink = BufferGetBlockNumber( rbuffer );
+ GinPageGetOpaque(rpage)->rightlink = data->rrlink;
+
+ if ( data->isData ) {
+ char *ptr = XLogRecGetData(record) + sizeof(ginxlogSplit);
+ Size sizeofitem = GinSizeOfItem(lpage);
+ OffsetNumber i;
+ ItemPointer bound;
+
+ for(i=0;iseparator;i++) {
+ GinDataPageAddItem( lpage, ptr, InvalidOffsetNumber );
+ ptr += sizeofitem;
+ }
+
+ for(i=data->separator;initem;i++) {
+ GinDataPageAddItem( rpage, ptr, InvalidOffsetNumber );
+ ptr += sizeofitem;
+ }
+
+ /* set up right key */
+ bound = GinDataPageGetRightBound(lpage);
+ if ( data->isLeaf )
+ *bound = *(ItemPointerData*)GinDataPageGetItem(lpage, GinPageGetOpaque(lpage)->maxoff);
+ else
+ *bound = ((PostingItem*)GinDataPageGetItem(lpage, GinPageGetOpaque(lpage)->maxoff))->key;
+
+ bound = GinDataPageGetRightBound(rpage);
+ *bound = data->rightbound;
+ } else {
+ IndexTuple itup = (IndexTuple)( XLogRecGetData(record) + sizeof(ginxlogSplit) );
+ OffsetNumber i;
+
+ for(i=0;iseparator;i++) {
+ if ( PageAddItem( lpage, (Item)itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber )
+ elog(ERROR, "failed to add item to index page in %u/%u/%u",
+ data->node.spcNode, data->node.dbNode, data->node.relNode );
+ itup = (IndexTuple)( ((char*)itup) + MAXALIGN( IndexTupleSize(itup) ) );
+ }
+
+ for(i=data->separator;initem;i++) {
+ if ( PageAddItem( rpage, (Item)itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber )
+ elog(ERROR, "failed to add item to index page in %u/%u/%u",
+ data->node.spcNode, data->node.dbNode, data->node.relNode );
+ itup = (IndexTuple)( ((char*)itup) + MAXALIGN( IndexTupleSize(itup) ) );
+ }
+ }
+
+ PageSetLSN(rpage, lsn);
+ PageSetTLI(lpage, ThisTimeLineID);
+ MarkBufferDirty(rbuffer);
+
+ PageSetLSN(lpage, lsn);
+ PageSetTLI(lpage, ThisTimeLineID);
+ MarkBufferDirty(lbuffer);
+
+ if ( !data->isLeaf && data->updateBlkno != InvalidBlockNumber )
+ forgetIncompleteSplit(data->node, data->leftChildBlkno, data->updateBlkno);
+
+ if ( data->isRootSplit ) {
+ Buffer rootBuf = XLogReadBuffer(reln, data->rootBlkno, false);
+ Page rootPage = BufferGetPage( rootBuf );
+
+ GinInitBuffer( rootBuf, flags & ~GIN_LEAF );
+
+ if ( data->isData ) {
+ Assert( data->rootBlkno != GIN_ROOT_BLKNO );
+ dataFillRoot(NULL, rootBuf, lbuffer, rbuffer);
+ } else {
+ Assert( data->rootBlkno == GIN_ROOT_BLKNO );
+ entryFillRoot(NULL, rootBuf, lbuffer, rbuffer);
+ }
+
+ PageSetLSN(rootPage, lsn);
+ PageSetTLI(rootPage, ThisTimeLineID);
+
+ MarkBufferDirty(rootBuf);
+ UnlockReleaseBuffer(rootBuf);
+ } else
+ pushIncompleteSplit(data->node, data->lblkno, data->rblkno, data->rootBlkno);
+
+ UnlockReleaseBuffer(rbuffer);
+ UnlockReleaseBuffer(lbuffer);
+}
+
+static void
+ginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record) {
+ ginxlogVacuumPage *data = (ginxlogVacuumPage*)XLogRecGetData(record);
+ Relation reln;
+ Buffer buffer;
+ Page page;
+
+ /* nothing else to do if page was backed up (and no info to do it with) */
+ if (record->xl_info & XLR_BKP_BLOCK_1)
+ return;
+
+ reln = XLogOpenRelation(data->node);
+ buffer = XLogReadBuffer(reln, data->blkno, false);
+ Assert(BufferIsValid(buffer));
+ page = (Page) BufferGetPage(buffer);
+
+ if ( GinPageIsData( page ) ) {
+ memcpy( GinDataPageGetData(page), XLogRecGetData(record) + sizeof(ginxlogVacuumPage),
+ GinSizeOfItem(page) * data->nitem );
+ GinPageGetOpaque(page)->maxoff = data->nitem;
+ } else {
+ OffsetNumber i, *tod;
+ IndexTuple itup = (IndexTuple)( XLogRecGetData(record) + sizeof(ginxlogVacuumPage) );
+
+ tod = (OffsetNumber*)palloc( sizeof(OffsetNumber) * PageGetMaxOffsetNumber(page) );
+ for(i=FirstOffsetNumber;i<=PageGetMaxOffsetNumber(page);i++)
+ tod[i-1] = i;
+
+ PageIndexMultiDelete(page, tod, PageGetMaxOffsetNumber(page));
+
+ for(i=0;initem;i++) {
+ if ( PageAddItem( page, (Item)itup, IndexTupleSize(itup), InvalidOffsetNumber, LP_USED) == InvalidOffsetNumber )
+ elog(ERROR, "failed to add item to index page in %u/%u/%u",
+ data->node.spcNode, data->node.dbNode, data->node.relNode );
+ itup = (IndexTuple)( ((char*)itup) + MAXALIGN( IndexTupleSize(itup) ) );
+ }
+ }
+
+ PageSetLSN(page, lsn);
+ PageSetTLI(page, ThisTimeLineID);
+
+ MarkBufferDirty(buffer);
+ UnlockReleaseBuffer(buffer);
+}
+
+static void
+ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record) {
+ ginxlogDeletePage *data = (ginxlogDeletePage*)XLogRecGetData(record);
+ Relation reln;
+ Buffer buffer;
+ Page page;
+
+ reln = XLogOpenRelation(data->node);
+
+ if ( !( record->xl_info & XLR_BKP_BLOCK_1) ) {
+ buffer = XLogReadBuffer(reln, data->blkno, false);
+ page = BufferGetPage( buffer );
+ Assert(GinPageIsData(page));
+ GinPageGetOpaque(page)->flags = GIN_DELETED;
+ PageSetLSN(page, lsn);
+ PageSetTLI(page, ThisTimeLineID);
+ MarkBufferDirty(buffer);
+ UnlockReleaseBuffer(buffer);
+ }
+
+ if ( !( record->xl_info & XLR_BKP_BLOCK_2) ) {
+ buffer = XLogReadBuffer(reln, data->parentBlkno, false);
+ page = BufferGetPage( buffer );
+ Assert(GinPageIsData(page));
+ Assert(!GinPageIsLeaf(page));
+ PageDeletePostingItem(page, data->parentOffset);
+ PageSetLSN(page, lsn);
+ PageSetTLI(page, ThisTimeLineID);
+ MarkBufferDirty(buffer);
+ UnlockReleaseBuffer(buffer);
+ }
+
+ if ( !( record->xl_info & XLR_BKP_BLOCK_2) && data->leftBlkno != InvalidBlockNumber ) {
+ buffer = XLogReadBuffer(reln, data->leftBlkno, false);
+ page = BufferGetPage( buffer );
+ Assert(GinPageIsData(page));
+ GinPageGetOpaque(page)->rightlink = data->rightLink;
+ PageSetLSN(page, lsn);
+ PageSetTLI(page, ThisTimeLineID);
+ MarkBufferDirty(buffer);
+ UnlockReleaseBuffer(buffer);
+ }
+}
+
+void
+gin_redo(XLogRecPtr lsn, XLogRecord *record) {
+ uint8 info = record->xl_info & ~XLR_INFO_MASK;
+
+ topCtx = MemoryContextSwitchTo(opCtx);
+ switch (info) {
+ case XLOG_GIN_CREATE_INDEX:
+ ginRedoCreateIndex(lsn, record);
+ break;
+ case XLOG_GIN_CREATE_PTREE:
+ ginRedoCreatePTree(lsn, record);
+ break;
+ case XLOG_GIN_INSERT:
+ ginRedoInsert(lsn, record);
+ break;
+ case XLOG_GIN_SPLIT:
+ ginRedoSplit(lsn, record);
+ break;
+ case XLOG_GIN_VACUUM_PAGE:
+ ginRedoVacuumPage(lsn, record);
+ break;
+ case XLOG_GIN_DELETE_PAGE:
+ ginRedoDeletePage(lsn, record);
+ break;
+ default:
+ elog(PANIC, "gin_redo: unknown op code %u", info);
+ }
+ MemoryContextSwitchTo(topCtx);
+ MemoryContextReset(opCtx);
+}
+
+static void
+desc_node( StringInfo buf, RelFileNode node, BlockNumber blkno ) {
+ appendStringInfo(buf,"node: %u/%u/%u blkno: %u",
+ node.spcNode, node.dbNode, node.relNode, blkno);
+}
+
+void
+gin_desc(StringInfo buf, uint8 xl_info, char *rec) {
+ uint8 info = xl_info & ~XLR_INFO_MASK;
+
+ switch (info) {
+ case XLOG_GIN_CREATE_INDEX:
+ appendStringInfo(buf,"Create index, ");
+ desc_node(buf, *(RelFileNode*)rec, GIN_ROOT_BLKNO );
+ break;
+ case XLOG_GIN_CREATE_PTREE:
+ appendStringInfo(buf,"Create posting tree, ");
+ desc_node(buf, ((ginxlogCreatePostingTree*)rec)->node, ((ginxlogCreatePostingTree*)rec)->blkno );
+ break;
+ case XLOG_GIN_INSERT:
+ appendStringInfo(buf,"Insert item, ");
+ desc_node(buf, ((ginxlogInsert*)rec)->node, ((ginxlogInsert*)rec)->blkno );
+ appendStringInfo(buf," offset: %u nitem: %u isdata: %c isleaf %c isdelete %c updateBlkno:%u",
+ ((ginxlogInsert*)rec)->offset,
+ ((ginxlogInsert*)rec)->nitem,
+ ( ((ginxlogInsert*)rec)->isData ) ? 'T' : 'F',
+ ( ((ginxlogInsert*)rec)->isLeaf ) ? 'T' : 'F',
+ ( ((ginxlogInsert*)rec)->isDelete ) ? 'T' : 'F',
+ ((ginxlogInsert*)rec)->updateBlkno
+ );
+
+ break;
+ case XLOG_GIN_SPLIT:
+ appendStringInfo(buf,"Page split, ");
+ desc_node(buf, ((ginxlogSplit*)rec)->node, ((ginxlogSplit*)rec)->lblkno );
+ appendStringInfo(buf," isrootsplit: %c", ( ((ginxlogSplit*)rec)->isRootSplit ) ? 'T' : 'F');
+ break;
+ case XLOG_GIN_VACUUM_PAGE:
+ appendStringInfo(buf,"Vacuum page, ");
+ desc_node(buf, ((ginxlogVacuumPage*)rec)->node, ((ginxlogVacuumPage*)rec)->blkno );
+ break;
+ case XLOG_GIN_DELETE_PAGE:
+ appendStringInfo(buf,"Delete page, ");
+ desc_node(buf, ((ginxlogDeletePage*)rec)->node, ((ginxlogDeletePage*)rec)->blkno );
+ break;
+ default:
+ elog(PANIC, "gin_desc: unknown op code %u", info);
+ }
+}
+
+void
+gin_xlog_startup(void) {
+ incomplete_splits = NIL;
+
+ opCtx = AllocSetContextCreate(CurrentMemoryContext,
+ "GIN recovery temporary context",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
+}
+
+static void
+ginContinueSplit( ginIncompleteSplit *split ) {
+ GinBtreeData btree;
+ Relation reln;
+ Buffer buffer;
+ GinBtreeStack stack;
+
+ /* elog(NOTICE,"ginContinueSplit root:%u l:%u r:%u", split->rootBlkno, split->leftBlkno, split->rightBlkno); */
+ reln = XLogOpenRelation(split->node);
+
+ buffer = XLogReadBuffer(reln, split->leftBlkno, false);
+
+ if ( split->rootBlkno == GIN_ROOT_BLKNO ) {
+ prepareEntryScan( &btree, reln, (Datum)0, NULL );
+ btree.entry = ginPageGetLinkItup( buffer );
+ } else {
+ Page page = BufferGetPage( buffer );
+
+ prepareDataScan( &btree, reln );
+
+ PostingItemSetBlockNumber( &(btree.pitem), split->leftBlkno );
+ if ( GinPageIsLeaf(page) )
+ btree.pitem.key = *(ItemPointerData*)GinDataPageGetItem(page,
+ GinPageGetOpaque(page)->maxoff);
+ else
+ btree.pitem.key = ((PostingItem*)GinDataPageGetItem(page,
+ GinPageGetOpaque(page)->maxoff))->key;
+ }
+
+ btree.rightblkno = split->rightBlkno;
+
+ stack.blkno = split->leftBlkno;
+ stack.buffer = buffer;
+ stack.off = InvalidOffsetNumber;
+ stack.parent = NULL;
+
+ findParents( &btree, &stack, split->rootBlkno);
+ ginInsertValue( &btree, stack.parent );
+
+ UnlockReleaseBuffer( buffer );
+}
+
+void
+gin_xlog_cleanup(void) {
+ ListCell *l;
+ MemoryContext topCtx;
+
+ topCtx = MemoryContextSwitchTo(opCtx);
+
+ foreach(l, incomplete_splits) {
+ ginIncompleteSplit *split = (ginIncompleteSplit *) lfirst(l);
+ ginContinueSplit( split );
+ MemoryContextReset( opCtx );
+ }
+
+ MemoryContextSwitchTo(topCtx);
+ MemoryContextDelete(opCtx);
+}
+
*
* Resource managers definition
*
- * $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.21 2005/11/07 17:36:45 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.22 2006/05/02 11:28:54 teodor Exp $
*/
#include "postgres.h"
#include "access/heapam.h"
#include "access/multixact.h"
#include "access/nbtree.h"
+#include "access/gin.h"
#include "access/xact.h"
#include "access/xlog_internal.h"
#include "commands/dbcommands.h"
{"Heap", heap_redo, heap_desc, NULL, NULL},
{"Btree", btree_redo, btree_desc, btree_xlog_startup, btree_xlog_cleanup},
{"Hash", hash_redo, hash_desc, NULL, NULL},
- {"Reserved 13", NULL, NULL, NULL, NULL},
+ {"Gin", gin_redo, gin_desc, gin_xlog_startup, gin_xlog_cleanup},
{"Gist", gist_redo, gist_desc, gist_xlog_startup, gist_xlog_cleanup},
{"Sequence", seq_redo, seq_desc, NULL, NULL}
};
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.144 2006/03/05 15:58:23 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.145 2006/05/02 11:28:54 teodor Exp $
*
*-------------------------------------------------------------------------
*/
RelationGetRelationName(OldIndex))));
}
+ if (!OldIndex->rd_am->amclusterable)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot cluster on index \"%s\" because access method does not clusterable",
+ RelationGetRelationName(OldIndex))));
+
+
/*
* Disallow clustering system relations. This will definitely NOT work
* for shared relations (we have no way to update pg_class rows in other
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.43 2006/03/14 22:48:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.44 2006/05/02 11:28:54 teodor Exp $
*
*-------------------------------------------------------------------------
*/
else
{
/*
- * Currently, only GiST allows storagetype different from
+ * Currently, only GiST and GIN allows storagetype different from
* datatype. This hardcoded test should be eliminated in favor of
* adding another boolean column to pg_am ...
*/
- if (amoid != GIST_AM_OID)
+ if (!(amoid == GIST_AM_OID || amoid == GIN_AM_OID))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("storage type may not be different from data type for access method \"%s\"",
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.326 2006/03/31 23:32:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.327 2006/05/02 11:28:54 teodor Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Check for tuple count mismatch. If the index is partial, then it's OK
* for it to have fewer tuples than the heap; else we got trouble.
+ *
+ * XXX Hack. Since GIN stores every pointer to heap several times and
+ * counting num_index_tuples during vacuum is very comlpex and slow
+ * we just copy num_tuples to num_index_tuples as upper limit to avoid
+ * WARNING and optimizer mistakes.
*/
+ if ( indrel->rd_rel->relam == GIN_AM_OID )
+ {
+ stats->num_index_tuples = num_tuples;
+ } else
if (stats->num_index_tuples != num_tuples)
{
if (stats->num_index_tuples > num_tuples ||
/*
* Check for tuple count mismatch. If the index is partial, then it's OK
* for it to have fewer tuples than the heap; else we got trouble.
+ *
+ * XXX Hack. Since GIN stores every pointer to heap several times and
+ * counting num_index_tuples during vacuum is very comlpex and slow
+ * we just copy num_tuples to num_index_tuples as upper limit to avoid
+ * WARNING and optimizer mistakes.
*/
+ if ( indrel->rd_rel->relam == GIN_AM_OID )
+ {
+ stats->num_index_tuples = num_tuples;
+ } else
if (stats->num_index_tuples != num_tuples + keep_tuples)
{
if (stats->num_index_tuples > num_tuples + keep_tuples ||
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.204 2006/05/02 04:34:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.205 2006/05/02 11:28:55 teodor Exp $
*
*-------------------------------------------------------------------------
*/
PG_RETURN_VOID();
}
+
+Datum
+gincostestimate(PG_FUNCTION_ARGS)
+{
+ PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
+ IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
+ List *indexQuals = (List *) PG_GETARG_POINTER(2);
+ Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
+ Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
+ Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
+ double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
+
+ genericcostestimate(root, index, indexQuals, 0.0,
+ indexStartupCost, indexTotalCost,
+ indexSelectivity, indexCorrelation);
+
+ PG_RETURN_VOID();
+}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.97 2006/03/05 15:58:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.98 2006/05/02 11:28:55 teodor Exp $
*
* NOTES
* Globals used all over the place should be declared here and not
int VacuumCostBalance = 0; /* working state for vacuum */
bool VacuumCostActive = false;
+
+int GinFuzzySearchLimit = 0;
* Written by Peter Eisentraut
.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.317 2006/04/25 14:11:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.318 2006/05/02 11:28:55 teodor Exp $
*
*--------------------------------------------------------------------
*/
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "pgstat.h"
-
+#include "access/gin.h"
#ifndef PG_KRB_SRVTAB
#define PG_KRB_SRVTAB ""
0, 0, INT_MAX, assign_tcp_keepalives_count, show_tcp_keepalives_count
},
+ {
+ {"gin_fuzzy_search_limit", PGC_USERSET, UNGROUPED,
+ gettext_noop("Sets the maximum allowed result for exact search by gin."),
+ NULL,
+ 0
+ },
+ &GinFuzzySearchLimit,
+ 0, 0, INT_MAX, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
--- /dev/null
+/*--------------------------------------------------------------------------
+ * gin.h
+ * header file for postgres inverted index access method implementation.
+ *
+ * Copyright (c) 2006, PostgreSQL Global Development Group
+ * $PostgreSQL: pgsql/src/include/access/gin.h,v 1.1 2006/05/02 11:28:55 teodor Exp $
+ *--------------------------------------------------------------------------
+ */
+
+
+#ifndef GIN_H
+#define GIN_H
+
+#include "access/xlog.h"
+#include "access/xlogdefs.h"
+#include "storage/bufpage.h"
+#include "storage/off.h"
+#include "utils/rel.h"
+#include "access/itup.h"
+#include "fmgr.h"
+
+
+/*
+ * amproc indexes for inverted indexes.
+ */
+#define GIN_COMPARE_PROC 1
+#define GIN_EXTRACTVALUE_PROC 2
+#define GIN_EXTRACTQUERY_PROC 3
+#define GIN_CONSISTENT_PROC 4
+#define GINNProcs 4
+
+typedef XLogRecPtr GinNSN;
+
+/*
+ * Page opaque data in a inverted index page.
+ */
+typedef struct GinPageOpaqueData {
+ uint16 flags;
+ OffsetNumber maxoff; /* number entries on GIN_DATA page:
+ number of heap ItemPointer on GIN_DATA|GIN_LEAF page
+ and number of records on GIN_DATA & ~GIN_LEAF page
+ */
+ BlockNumber rightlink;
+} GinPageOpaqueData;
+
+typedef GinPageOpaqueData *GinPageOpaque;
+
+#define GIN_ROOT_BLKNO (0)
+
+typedef struct {
+ BlockIdData child_blkno; /* use it instead of BlockNumber to
+ save space on page */
+ ItemPointerData key;
+} PostingItem;
+
+#define PostingItemGetBlockNumber(pointer) \
+ BlockIdGetBlockNumber(&(pointer)->child_blkno)
+
+#define PostingItemSetBlockNumber(pointer, blockNumber) \
+ BlockIdSet(&((pointer)->child_blkno), (blockNumber))
+
+/*
+ * Page opaque data in a inverted index page.
+ */
+#define GIN_DATA (1 << 0)
+#define GIN_LEAF (1 << 1)
+#define GIN_DELETED (1 << 2)
+
+/*
+ * Works on page
+ */
+#define GinPageGetOpaque(page) ( (GinPageOpaque) PageGetSpecialPointer(page) )
+
+#define GinPageIsLeaf(page) ( GinPageGetOpaque(page)->flags & GIN_LEAF )
+#define GinPageSetLeaf(page) ( GinPageGetOpaque(page)->flags |= GIN_LEAF )
+#define GinPageSetNonLeaf(page) ( GinPageGetOpaque(page)->flags &= ~GIN_LEAF )
+#define GinPageIsData(page) ( GinPageGetOpaque(page)->flags & GIN_DATA )
+#define GinPageSetData(page) ( GinPageGetOpaque(page)->flags |= GIN_DATA )
+
+#define GinPageIsDeleted(page) ( GinPageGetOpaque(page)->flags & GIN_DELETED)
+#define GinPageSetDeleted(page) ( GinPageGetOpaque(page)->flags |= GIN_DELETED)
+#define GinPageSetNonDeleted(page) ( GinPageGetOpaque(page)->flags &= ~GIN_DELETED)
+
+#define GinPageRightMost(page) ( GinPageGetOpaque(page)->rightlink == InvalidBlockNumber)
+
+/*
+ * Define our ItemPointerGet(BlockNumber|GetOffsetNumber)
+ * to prevent asserts
+ */
+
+#define GinItemPointerGetBlockNumber(pointer) \
+ BlockIdGetBlockNumber(&(pointer)->ip_blkid)
+
+#define GinItemPointerGetOffsetNumber(pointer) \
+ ((pointer)->ip_posid)
+
+/*
+ * Support work on IndexTuuple on leaf pages
+ */
+#define GinGetNPosting(itup) GinItemPointerGetOffsetNumber(&(itup)->t_tid)
+#define GinSetNPosting(itup,n) ItemPointerSetOffsetNumber(&(itup)->t_tid,(n))
+#define GIN_TREE_POSTING ((OffsetNumber)0xffff)
+#define GinIsPostingTree(itup) ( GinGetNPosting(itup)==GIN_TREE_POSTING )
+#define GinSetPostingTree(itup, blkno) ( GinSetNPosting((itup),GIN_TREE_POSTING ), ItemPointerSetBlockNumber(&(itup)->t_tid, blkno) )
+#define GinGetPostingTree(itup) GinItemPointerGetBlockNumber(&(itup)->t_tid)
+
+#define GinGetOrigSizePosting(itup) GinItemPointerGetBlockNumber(&(itup)->t_tid)
+#define GinSetOrigSizePosting(itup,n) ItemPointerSetBlockNumber(&(itup)->t_tid,(n))
+#define GinGetPosting(itup) ( (ItemPointer)(( ((char*)(itup)) + SHORTALIGN(GinGetOrigSizePosting(itup)) )) )
+
+#define GinMaxItemSize \
+ ((BLCKSZ - SizeOfPageHeaderData - \
+ MAXALIGN(sizeof(GinPageOpaqueData))) / 3 - sizeof(ItemIdData))
+
+
+/*
+ * Data (posting tree) pages
+ */
+#define GinDataPageGetData(page) \
+ (PageGetContents(page)+MAXALIGN(sizeof(ItemPointerData)))
+#define GinDataPageGetRightBound(page) ((ItemPointer)PageGetContents(page))
+#define GinSizeOfItem(page) ( (GinPageIsLeaf(page)) ? sizeof(ItemPointerData) : sizeof(PostingItem) )
+#define GinDataPageGetItem(page,i) ( GinDataPageGetData(page) + ((i)-1) * GinSizeOfItem(page) )
+
+#define GinDataPageGetFreeSpace(page) \
+ ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GinPageOpaqueData)) - \
+ GinPageGetOpaque(page)->maxoff * GinSizeOfItem(page) - \
+ MAXALIGN(sizeof(ItemPointerData)))
+
+
+
+#define GIN_UNLOCK BUFFER_LOCK_UNLOCK
+#define GIN_SHARE BUFFER_LOCK_SHARE
+#define GIN_EXCLUSIVE BUFFER_LOCK_EXCLUSIVE
+
+typedef struct GinState {
+ FmgrInfo compareFn;
+ FmgrInfo extractValueFn;
+ FmgrInfo extractQueryFn;
+ FmgrInfo consistentFn;
+
+ TupleDesc tupdesc;
+} GinState;
+
+/* XLog stuff */
+
+#define XLOG_GIN_CREATE_INDEX 0x00
+
+#define XLOG_GIN_CREATE_PTREE 0x10
+
+typedef struct ginxlogCreatePostingTree {
+ RelFileNode node;
+ BlockNumber blkno;
+ uint32 nitem;
+ /* follows list of heap's ItemPointer */
+} ginxlogCreatePostingTree;
+
+#define XLOG_GIN_INSERT 0x20
+
+typedef struct ginxlogInsert {
+ RelFileNode node;
+ BlockNumber blkno;
+ BlockNumber updateBlkno;
+ OffsetNumber offset;
+ bool isDelete;
+ bool isData;
+ bool isLeaf;
+ OffsetNumber nitem;
+
+ /* follows: tuples or ItemPointerData or PostingItem or list of ItemPointerData*/
+} ginxlogInsert;
+
+#define XLOG_GIN_SPLIT 0x30
+
+typedef struct ginxlogSplit {
+ RelFileNode node;
+ BlockNumber lblkno;
+ BlockNumber rootBlkno;
+ BlockNumber rblkno;
+ BlockNumber rrlink;
+ OffsetNumber separator;
+ OffsetNumber nitem;
+
+ bool isData;
+ bool isLeaf;
+ bool isRootSplit;
+
+ BlockNumber leftChildBlkno;
+ BlockNumber updateBlkno;
+
+ ItemPointerData rightbound; /* used only in posting tree */
+ /* follows: list of tuple or ItemPointerData or PostingItem */
+} ginxlogSplit;
+
+#define XLOG_GIN_VACUUM_PAGE 0x40
+
+typedef struct ginxlogVacuumPage {
+ RelFileNode node;
+ BlockNumber blkno;
+ OffsetNumber nitem;
+ /* follows content of page */
+} ginxlogVacuumPage;
+
+#define XLOG_GIN_DELETE_PAGE 0x50
+
+typedef struct ginxlogDeletePage {
+ RelFileNode node;
+ BlockNumber blkno;
+ BlockNumber parentBlkno;
+ OffsetNumber parentOffset;
+ BlockNumber leftBlkno;
+ BlockNumber rightLink;
+} ginxlogDeletePage;
+
+/* ginutil.c */
+extern void initGinState( GinState *state, Relation index );
+extern Buffer GinNewBuffer(Relation index);
+extern void GinInitBuffer(Buffer b, uint32 f);
+extern void GinInitPage(Page page, uint32 f, Size pageSize);
+extern int compareEntries(GinState *ginstate, Datum a, Datum b);
+extern Datum* extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries);
+extern Datum* extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries);
+extern Page GinPageGetCopyPage( Page page );
+
+/* gininsert.c */
+extern Datum ginbuild(PG_FUNCTION_ARGS);
+extern Datum gininsert(PG_FUNCTION_ARGS);
+
+/* ginxlog.c */
+extern void gin_redo(XLogRecPtr lsn, XLogRecord *record);
+extern void gin_desc(StringInfo buf, uint8 xl_info, char *rec);
+extern void gin_xlog_startup(void);
+extern void gin_xlog_cleanup(void);
+
+/* ginbtree.c */
+
+typedef struct GinBtreeStack {
+ BlockNumber blkno;
+ Buffer buffer;
+ OffsetNumber off;
+ /* predictNumber contains prediction number of pages on current level */
+ uint32 predictNumber;
+ struct GinBtreeStack *parent;
+} GinBtreeStack;
+
+typedef struct GinBtreeData *GinBtree;
+
+typedef struct GinBtreeData {
+ /* search methods */
+ BlockNumber (*findChildPage)(GinBtree, GinBtreeStack *);
+ bool (*isMoveRight)(GinBtree, Page);
+ bool (*findItem)(GinBtree, GinBtreeStack *);
+
+ /* insert methods */
+ OffsetNumber (*findChildPtr)(GinBtree, Page, BlockNumber, OffsetNumber);
+ BlockNumber (*getLeftMostPage)(GinBtree, Page);
+ bool (*isEnoughSpace)(GinBtree, Buffer, OffsetNumber);
+ void (*placeToPage)(GinBtree, Buffer, OffsetNumber, XLogRecData**);
+ Page (*splitPage)(GinBtree, Buffer, Buffer, OffsetNumber, XLogRecData**);
+ void (*fillRoot)(GinBtree, Buffer, Buffer, Buffer);
+
+ bool searchMode;
+
+ Relation index;
+ GinState *ginstate;
+ bool fullScan;
+ bool isBuild;
+
+ BlockNumber rightblkno;
+
+ /* Entry options */
+ Datum entryValue;
+ IndexTuple entry;
+ bool isDelete;
+
+ /* Data (posting tree) option */
+ ItemPointerData *items;
+ uint32 nitem;
+ uint32 curitem;
+
+ PostingItem pitem;
+} GinBtreeData;
+
+extern GinBtreeStack* ginPrepareFindLeafPage(GinBtree btree, BlockNumber blkno);
+extern GinBtreeStack* ginFindLeafPage(GinBtree btree, GinBtreeStack *stack );
+extern void freeGinBtreeStack( GinBtreeStack *stack );
+extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack);
+extern void findParents( GinBtree btree, GinBtreeStack *stack, BlockNumber rootBlkno);
+
+/* ginentrypage.c */
+extern IndexTuple GinFormTuple(GinState *ginstate, Datum key, ItemPointerData *ipd, uint32 nipd);
+extern Datum ginGetHighKey(GinState *ginstate, Page page);
+extern void prepareEntryScan( GinBtree btree, Relation index, Datum value, GinState *ginstate);
+extern void entryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf);
+extern IndexTuple ginPageGetLinkItup(Buffer buf);
+
+/* gindatapage.c */
+extern int compareItemPointers( ItemPointer a, ItemPointer b );
+extern void MergeItemPointers(
+ ItemPointerData *dst,
+ ItemPointerData *a, uint32 na,
+ ItemPointerData *b, uint32 nb
+ );
+
+extern void GinDataPageAddItem( Page page, void *data, OffsetNumber offset );
+extern void PageDeletePostingItem(Page page, OffsetNumber offset);
+
+typedef struct {
+ GinBtreeData btree;
+ GinBtreeStack *stack;
+} GinPostingTreeScan;
+
+extern GinPostingTreeScan* prepareScanPostingTree( Relation index,
+ BlockNumber rootBlkno, bool searchMode);
+extern void insertItemPointer(GinPostingTreeScan *gdi,
+ ItemPointerData *items, uint32 nitem);
+extern Buffer scanBeginPostingTree( GinPostingTreeScan *gdi );
+extern void dataFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf);
+extern void prepareDataScan( GinBtree btree, Relation index);
+/* ginscan.c */
+
+typedef struct GinScanEntryData *GinScanEntry;
+
+typedef struct GinScanEntryData {
+ /* link to the equals entry in current scan key */
+ GinScanEntry master;
+
+ /* link to values reported to consistentFn,
+ points to GinScanKey->entryRes[i]*/
+ bool *pval;
+
+ /* entry, got from extractQueryFn */
+ Datum entry;
+
+ /* current ItemPointer to heap, its offset in buffer and buffer */
+ ItemPointerData curItem;
+ OffsetNumber offset;
+ Buffer buffer;
+
+ /* in case of Posing list */
+ ItemPointerData *list;
+ uint32 nlist;
+
+ bool isFinished;
+ bool reduceResult;
+ uint32 predictNumberResult;
+} GinScanEntryData;
+
+typedef struct GinScanKeyData {
+ /* Number of entries in query (got by extractQueryFn) */
+ uint32 nentries;
+
+ /* array of ItemPointer result, reported to consistentFn */
+ bool *entryRes;
+
+ /* array of scans per entry */
+ GinScanEntry scanEntry;
+
+ /* for calling consistentFn(GinScanKey->entryRes, strategy, query) */
+ StrategyNumber strategy;
+ Datum query;
+
+ ItemPointerData curItem;
+ bool firstCall;
+ bool isFinished;
+} GinScanKeyData;
+
+typedef GinScanKeyData *GinScanKey;
+
+typedef struct GinScanOpaqueData {
+ MemoryContext tempCtx;
+ GinState ginstate;
+
+ GinScanKey keys;
+ uint32 nkeys;
+
+ GinScanKey markPos;
+} GinScanOpaqueData;
+
+typedef GinScanOpaqueData *GinScanOpaque;
+
+extern Datum ginbeginscan(PG_FUNCTION_ARGS);
+extern Datum ginendscan(PG_FUNCTION_ARGS);
+extern Datum ginrescan(PG_FUNCTION_ARGS);
+extern Datum ginmarkpos(PG_FUNCTION_ARGS);
+extern Datum ginrestrpos(PG_FUNCTION_ARGS);
+extern void newScanKey( IndexScanDesc scan );
+
+/* ginget.c */
+extern DLLIMPORT int GinFuzzySearchLimit;
+
+#define ItemPointerSetMax(p) ItemPointerSet( (p), (BlockNumber)0xffffffff, (OffsetNumber)0xffff )
+#define ItemPointerIsMax(p) ( ItemPointerGetBlockNumber(p) == (BlockNumber)0xffffffff && ItemPointerGetOffsetNumber(p) == (OffsetNumber)0xffff )
+#define ItemPointerSetMin(p) ItemPointerSet( (p), (BlockNumber)0, (OffsetNumber)0)
+#define ItemPointerIsMin(p) ( ItemPointerGetBlockNumber(p) == (BlockNumber)0 && ItemPointerGetOffsetNumber(p) == (OffsetNumber)0 )
+
+extern Datum gingetmulti(PG_FUNCTION_ARGS);
+extern Datum gingettuple(PG_FUNCTION_ARGS);
+
+/* ginvacuum.c */
+extern Datum ginbulkdelete(PG_FUNCTION_ARGS);
+extern Datum ginvacuumcleanup(PG_FUNCTION_ARGS);
+
+/* ginarrayproc.c */
+extern Datum ginarrayextract(PG_FUNCTION_ARGS);
+extern Datum ginarrayconsistent(PG_FUNCTION_ARGS);
+
+/* I'm not sure that is the best place */
+extern Datum arrayoverlap(PG_FUNCTION_ARGS);
+extern Datum arraycontains(PG_FUNCTION_ARGS);
+extern Datum arraycontained(PG_FUNCTION_ARGS);
+
+/* ginbulk.c */
+typedef struct {
+ Datum value;
+ uint32 length;
+ uint32 number;
+ ItemPointerData *list;
+ bool shouldSort;
+} EntryAccumulator;
+
+typedef struct {
+ GinState *ginstate;
+ EntryAccumulator *entries;
+ uint32 length;
+ uint32 number;
+ uint32 curget;
+ uint32 allocatedMemory;
+} BuildAccumulator;
+
+extern void ginInitBA(BuildAccumulator *accum);
+extern void ginInsertRecordBA( BuildAccumulator *accum,
+ ItemPointer heapptr, Datum *entries, uint32 nentry );
+extern ItemPointerData* ginGetEntry(BuildAccumulator *accum, Datum *entry, uint32 *n);
+
+#endif
*
* Resource managers definition
*
- * $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.15 2005/11/07 17:36:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.16 2006/05/02 11:28:55 teodor Exp $
*/
#ifndef RMGR_H
#define RMGR_H
#define RM_HEAP_ID 10
#define RM_BTREE_ID 11
#define RM_HASH_ID 12
+#define RM_GIN_ID 13
#define RM_GIST_ID 14
#define RM_SEQ_ID 15
#define RM_MAX_ID RM_SEQ_ID
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.328 2006/04/30 18:30:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.329 2006/05/02 11:28:55 teodor Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200604301
+#define CATALOG_VERSION_NO 200605021
#endif
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.40 2006/03/05 15:58:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.41 2006/05/02 11:28:55 teodor Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
bool amoptionalkey; /* can query omit key for the first column? */
bool amindexnulls; /* does AM support NULL index entries? */
bool amconcurrent; /* does AM support concurrent updates? */
+ bool amclusterable; /* does AM support cluster command? */
regproc aminsert; /* "insert this tuple" function */
regproc ambeginscan; /* "start new scan" function */
regproc amgettuple; /* "next valid tuple" function */
* compiler constants for pg_am
* ----------------
*/
-#define Natts_pg_am 21
+#define Natts_pg_am 22
#define Anum_pg_am_amname 1
#define Anum_pg_am_amstrategies 2
#define Anum_pg_am_amsupport 3
#define Anum_pg_am_amoptionalkey 7
#define Anum_pg_am_amindexnulls 8
#define Anum_pg_am_amconcurrent 9
-#define Anum_pg_am_aminsert 10
-#define Anum_pg_am_ambeginscan 11
-#define Anum_pg_am_amgettuple 12
-#define Anum_pg_am_amgetmulti 13
-#define Anum_pg_am_amrescan 14
-#define Anum_pg_am_amendscan 15
-#define Anum_pg_am_ammarkpos 16
-#define Anum_pg_am_amrestrpos 17
-#define Anum_pg_am_ambuild 18
-#define Anum_pg_am_ambulkdelete 19
-#define Anum_pg_am_amvacuumcleanup 20
-#define Anum_pg_am_amcostestimate 21
+#define Anum_pg_am_amclusterable 10
+#define Anum_pg_am_aminsert 11
+#define Anum_pg_am_ambeginscan 12
+#define Anum_pg_am_amgettuple 13
+#define Anum_pg_am_amgetmulti 14
+#define Anum_pg_am_amrescan 15
+#define Anum_pg_am_amendscan 16
+#define Anum_pg_am_ammarkpos 17
+#define Anum_pg_am_amrestrpos 18
+#define Anum_pg_am_ambuild 19
+#define Anum_pg_am_ambulkdelete 20
+#define Anum_pg_am_amvacuumcleanup 21
+#define Anum_pg_am_amcostestimate 22
/* ----------------
* initial contents of pg_am
* ----------------
*/
-DATA(insert OID = 403 ( btree 5 1 1 t t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
+DATA(insert OID = 403 ( btree 5 1 1 t t t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
DESCR("b-tree index access method");
#define BTREE_AM_OID 403
-DATA(insert OID = 405 ( hash 1 1 0 f f f f t hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate ));
+DATA(insert OID = 405 ( hash 1 1 0 f f f f t f hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate ));
DESCR("hash index access method");
#define HASH_AM_OID 405
-DATA(insert OID = 783 ( gist 100 7 0 f t f f t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate ));
+DATA(insert OID = 783 ( gist 100 7 0 f t f f t t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate ));
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 ));
+DESCR("GIN index access method");
+#define GIN_AM_OID 2742
#endif /* PG_AM_H */
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.69 2006/03/05 15:58:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.70 2006/05/02 11:28:55 teodor Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
DATA(insert ( 2595 0 11 t 1514 ));
DATA(insert ( 2595 0 12 t 2590 ));
+/*
+ * gin _int4_ops
+ */
+DATA(insert ( 2745 0 1 f 2750 ));
+DATA(insert ( 2745 0 2 f 2751 ));
+DATA(insert ( 2745 0 3 t 2752 ));
+
+/*
+ * gin _text_ops
+ */
+DATA(insert ( 2746 0 1 f 2750 ));
+DATA(insert ( 2746 0 2 f 2751 ));
+DATA(insert ( 2746 0 3 t 2752 ));
+
#endif /* PG_AMOP_H */
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.56 2006/03/05 15:58:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.57 2006/05/02 11:28:55 teodor Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
DATA(insert ( 2595 0 6 2582 ));
DATA(insert ( 2595 0 7 2584 ));
+/* gin */
+DATA(insert ( 2745 0 1 351 ));
+DATA(insert ( 2745 0 2 2743 ));
+DATA(insert ( 2745 0 3 2743 ));
+DATA(insert ( 2745 0 4 2744 ));
+DATA(insert ( 2746 0 1 360 ));
+DATA(insert ( 2746 0 2 2743 ));
+DATA(insert ( 2746 0 3 2743 ));
+DATA(insert ( 2746 0 4 2744 ));
+
#endif /* PG_AMPROC_H */
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.68 2006/03/05 15:58:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.69 2006/05/02 11:28:55 teodor Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
DATA(insert OID = 2593 ( 783 box_ops PGNSP PGUID 603 t 0 ));
DATA(insert OID = 2594 ( 783 poly_ops PGNSP PGUID 604 t 603 ));
DATA(insert OID = 2595 ( 783 circle_ops PGNSP PGUID 718 t 603 ));
+DATA(insert OID = 2745 ( 2742 _int4_ops PGNSP PGUID 1007 t 23 ));
+DATA(insert OID = 2746 ( 2742 _text_ops PGNSP PGUID 1009 t 25 ));
#endif /* PG_OPCLASS_H */
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.142 2006/03/05 15:58:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.143 2006/05/02 11:28:55 teodor Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
DATA(insert OID = 2589 ( "&<|" PGNSP PGUID b f 718 718 16 0 0 0 0 0 0 circle_overbelow positionsel positionjoinsel ));
DATA(insert OID = 2590 ( "|&>" PGNSP PGUID b f 718 718 16 0 0 0 0 0 0 circle_overabove positionsel positionjoinsel ));
+/* overlap/contains/contained from arrays */
+DATA(insert OID = 2750 ( "&&" PGNSP PGUID b f 2277 2277 16 2750 0 0 0 0 0 arrayoverlap areasel areajoinsel ));
+DATA(insert OID = 2751 ( "@" PGNSP PGUID b f 2277 2277 16 2752 0 0 0 0 0 arraycontains contsel contjoinsel ));
+DATA(insert OID = 2752 ( "~" PGNSP PGUID b f 2277 2277 16 2751 0 0 0 0 0 arraycontained contsel contjoinsel ));
+
/*
* function prototypes
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.408 2006/04/26 22:33:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.409 2006/05/02 11:28:55 teodor Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
DATA(insert OID = 2592 ( gist_circle_compress PGNSP PGUID 12 f f t f i 1 2281 "2281" _null_ _null_ _null_ gist_circle_compress - _null_ ));
DESCR("GiST support");
+/* GIN */
+DATA(insert OID = 2730 ( gingettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ gingettuple - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2731 ( gingetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ gingetmulti - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2732 ( gininsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gininsert - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2733 ( ginbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ ginbeginscan - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2734 ( ginrescan PGNSP PGUID 12 f f t f v 2 2278 "2281 2281" _null_ _null_ _null_ ginrescan - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2735 ( ginendscan PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ ginendscan - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2736 ( ginmarkpos PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ ginmarkpos - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2737 ( ginrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ ginrestrpos - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2738 ( ginbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ ginbuild - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2739 ( ginbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ ginbulkdelete - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2740 ( ginvacuumcleanup PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ ginvacuumcleanup - _null_ ));
+DESCR("gin(internal)");
+DATA(insert OID = 2741 ( gincostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gincostestimate - _null_ ));
+DESCR("gin(internal)");
+
+/* GIN array support */
+DATA(insert OID = 2743 ( ginarrayextract PGNSP PGUID 12 f f t f i 2 2281 "2277 2281" _null_ _null_ _null_ ginarrayextract - _null_ ));
+DESCR("GIN array support");
+DATA(insert OID = 2744 ( ginarrayconsistent PGNSP PGUID 12 f f t f i 3 16 "2281 21 2281" _null_ _null_ _null_ ginarrayconsistent - _null_ ));
+DESCR("GIN array support");
+
+/* overlap/contains/contained */
+DATA(insert OID = 2747 ( arrayoverlap PGNSP PGUID 12 f f t f i 2 16 "2277 2277" _null_ _null_ _null_ arrayoverlap - _null_ ));
+DESCR("anyarray overlap");
+DATA(insert OID = 2748 ( arraycontains PGNSP PGUID 12 f f t f i 2 16 "2277 2277" _null_ _null_ _null_ arraycontains - _null_ ));
+DESCR("anyarray contains");
+DATA(insert OID = 2749 ( arraycontained PGNSP PGUID 12 f f t f i 2 16 "2277 2277" _null_ _null_ _null_ arraycontained - _null_ ));
+DESCR("anyarray contained");
/*
* Symbolic values for provolatile column: these indicate whether the result
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.32 2006/04/27 17:52:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.33 2006/05/02 11:28:55 teodor Exp $
*
*-------------------------------------------------------------------------
*/
extern Datum btcostestimate(PG_FUNCTION_ARGS);
extern Datum hashcostestimate(PG_FUNCTION_ARGS);
extern Datum gistcostestimate(PG_FUNCTION_ARGS);
+extern Datum gincostestimate(PG_FUNCTION_ARGS);
#endif /* SELFUNCS_H */
--- /dev/null
+1 {92,75,71,52,64,83} {AAAAAAAA44066,AAAAAA1059,AAAAAAAAAAA176,AAAAAAA48038}
+2 {3,6} {AAAAAA98232,AAAAAAAA79710,AAAAAAAAAAAAAAAAA69675,AAAAAAAAAAAAAAAA55798,AAAAAAAAA12793}
+3 {37,64,95,43,3,41,13,30,11,43} {AAAAAAAAAA48845,AAAAA75968,AAAAA95309,AAA54451,AAAAAAAAAA22292,AAAAAAA99836,A96617,AA17009,AAAAAAAAAAAAAA95246}
+4 {71,39,99,55,33,75,45} {AAAAAAAAA53663,AAAAAAAAAAAAAAA67062,AAAAAAAAAA64777,AAA99043,AAAAAAAAAAAAAAAAAAA91804,39557}
+5 {50,42,77,50,4} {AAAAAAAAAAAAAAAAA26540,AAAAAAA79710,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA176,AAAAA95309,AAAAAAAAAAA46154,AAAAAA66777,AAAAAAAAA27249,AAAAAAAAAA64777,AAAAAAAAAAAAAAAAAAA70104}
+6 {39,35,5,94,17,92,60,32} {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+7 {12,51,88,64,8} {AAAAAAAAAAAAAAAAAA12591,AAAAAAAAAAAAAAAAA50407,AAAAAAAAAAAA67946}
+8 {60,84} {AAAAAAA81898,AAAAAA1059,AAAAAAAAAAAA81511,AAAAA961,AAAAAAAAAAAAAAAA31334,AAAAA64741,AA6416,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAAAA50407}
+9 {56,52,35,27,80,44,81,22} {AAAAAAAAAAAAAAA73034,AAAAAAAAAAAAA7929,AAAAAAA66161,AA88409,39557,A27153,AAAAAAAA9523,AAAAAAAAAAA99000}
+10 {71,5,45} {AAAAAAAAAAA21658,AAAAAAAAAAAA21089,AAA54451,AAAAAAAAAAAAAAAAAA54141,AAAAAAAAAAAAAA28620,AAAAAAAAAAA21658,AAAAAAAAAAA74076,AAAAAAAAA27249}
+11 {41,86,74,48,22,74,47,50} {AAAAAAAA9523,AAAAAAAAAAAA37562,AAAAAAAAAAAAAAAA14047,AAAAAAAAAAA46154,AAAA41702,AAAAAAAAAAAAAAAAA764,AAAAA62737,39557}
+12 {17,99,18,52,91,72,0,43,96,23} {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576}
+13 {3,52,34,23} {AAAAAA98232,AAAA49534,AAAAAAAAAAA21658}
+14 {78,57,19} {AAAA8857,AAAAAAAAAAAAAAA73034,AAAAAAAA81587,AAAAAAAAAAAAAAA68526,AAAAA75968,AAAAAAAAAAAAAA65909,AAAAAAAAA10012,AAAAAAAAAAAAAA65909}
+15 {17,14,16,63,67} {AA6416,AAAAAAAAAA646,AAAAA95309}
+16 {14,63,85,11} {AAAAAA66777}
+17 {7,10,81,85} {AAAAAA43678,AAAAAAA12144,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAAAAA15356}
+18 {1} {AAAAAAAAAAA33576,AAAAA95309,64261,AAA59323,AAAAAAAAAAAAAA95246,55847,AAAAAAAAAAAA67946,AAAAAAAAAAAAAAAAAA64374}
+19 {52,82,17,74,23,46,69,51,75} {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938}
+20 {72,89,70,51,54,37,8,49,79} {AAAAAA58494}
+21 {2,8,65,10,5,79,43} {AAAAAAAAAAAAAAAAA88852,AAAAAAAAAAAAAAAAAAA91804,AAAAA64669,AAAAAAAAAAAAAAAA1443,AAAAAAAAAAAAAAAA23657,AAAAA12179,AAAAAAAAAAAAAAAAA88852,AAAAAAAAAAAAAAAA31334,AAAAAAAAAAAAAAAA41303,AAAAAAAAAAAAAAAAAAA85420}
+22 {11,6,56,62,53,30} {AAAAAAAA72908}
+23 {40,90,5,38,72,40,30,10,43,55} {A6053,AAAAAAAAAAA6119,AA44673,AAAAAAAAAAAAAAAAA764,AA17009,AAAAA17383,AAAAA70514,AAAAA33250,AAAAA95309,AAAAAAAAAAAA37562}
+24 {94,61,99,35,48} {AAAAAAAAAAA50956,AAAAAAAAAAA15165,AAAA85070,AAAAAAAAAAAAAAA36627,AAAAA961,AAAAAAAAAA55219}
+25 {31,1,10,11,27,79,38} {AAAAAAAAAAAAAAAAAA59334,45449}
+26 {71,10,9,69,75} {47735,AAAAAAA21462,AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAAAAA91804,AAAAAAAAA72121,AAAAAAAAAAAAAAAAAAA1205,AAAAA41597,AAAA8857,AAAAAAAAAAAAAAAAAAA15356,AA17009}
+27 {94} {AA6416,A6053,AAAAAAA21462,AAAAAAA57334,AAAAAAAAAAAAAAAAAA12591,AA88409,AAAAAAAAAAAAA70254}
+28 {14,33,6,34,14} {AAAAAAAAAAAAAAA13198,AAAAAAAA69452,AAAAAAAAAAA82945,AAAAAAA12144,AAAAAAAAA72121,AAAAAAAAAA18601}
+29 {39,21} {AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAAAAA38885,AAAA85070,AAAAAAAAAAAAAAAAAAA70104,AAAAA66674,AAAAAAAAAAAAA62007,AAAAAAAA69452,AAAAAAA1242,AAAAAAAAAAAAAAAA1729,AAAA35194}
+30 {26,81,47,91,34} {AAAAAAAAAAAAAAAAAAA70104,AAAAAAA80240}
+31 {80,24,18,21,54} {AAAAAAAAAAAAAAA13198,AAAAAAAAAAAAAAAAAAA70415,A27153,AAAAAAAAA53663,AAAAAAAAAAAAAAAAA50407,A68938}
+32 {58,79,82,80,67,75,98,10,41} {AAAAAAAAAAAAAAAAAA61286,AAA54451,AAAAAAAAAAAAAAAAAAA87527,A96617,51533}
+33 {74,73} {A85417,AAAAAAA56483,AAAAA17383,AAAAAAAAAAAAA62159,AAAAAAAAAAAA52814,AAAAAAAAAAAAA85723,AAAAAAAAAAAAAAAAAA55796}
+34 {70,45} {AAAAAAAAAAAAAAAAAA71621,AAAAAAAAAAAAAA28620,AAAAAAAAAA55219,AAAAAAAA23648,AAAAAAAAAA22292,AAAAAAA1242}
+35 {23,40} {AAAAAAAAAAAA52814,AAAA48949,AAAAAAAAA34727,AAAA8857,AAAAAAAAAAAAAAAAAAA62179,AAAAAAAAAAAAAAA68526,AAAAAAA99836,AAAAAAAA50094,AAAA91194,AAAAAAAAAAAAA73084}
+36 {79,82,14,52,30,5,79} {AAAAAAAAA53663,AAAAAAAAAAAAAAAA55798,AAAAAAAAAAAAAAAAAAA89194,AA88409,AAAAAAAAAAAAAAA81326,AAAAAAAAAAAAAAAAA63050,AAAAAAAAAAAAAAAA33598}
+37 {53,11,81,39,3,78,58,64,74} {AAAAAAAAAAAAAAAAAAA17075,AAAAAAA66161,AAAAAAAA23648,AAAAAAAAAAAAAA10611}
+38 {59,5,4,95,28} {AAAAAAAAAAA82945,A96617,47735,AAAAA12179,AAAAA64669,AAAAAA99807,AA74433,AAAAAAAAAAAAAAAAA59387}
+39 {82,43,99,16,74} {AAAAAAAAAAAAAAA67062,AAAAAAA57334,AAAAAAAAAAAAAA65909,A27153,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAA64777,AAAAAAAAAAAA81511,AAAAAAAAAAAAAA65909,AAAAAAAAAAAAAA28620}
+40 {34} {AAAAAAAAAAAAAA10611,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAA31334,AAAAA70466,AAAAAAAA81587,AAAAAAA74623}
+41 {19,26,63,12,93,73,27,94} {AAAAAAA79710,AAAAAAAAAA55219,AAAA41702,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAAA71621,AAAAAAAAAAAAAAAAA63050,AAAAAAA99836,AAAAAAAAAAAAAA8666}
+42 {15,76,82,75,8,91} {AAAAAAAAAAA176,AAAAAA38063,45449,AAAAAA54032,AAAAAAA81898,AA6416,AAAAAAAAAAAAAAAAAAA62179,45449,AAAAA60038,AAAAAAAA81587}
+43 {39,87,91,97,79,28} {AAAAAAAAAAA74076,A96617,AAAAAAAAAAAAAAAAAAA89194,AAAAAAAAAAAAAAAAAA55796,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAA67946}
+44 {40,58,68,29,54} {AAAAAAA81898,AAAAAA66777,AAAAAA98232}
+45 {99,45} {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+46 {53,24} {AAAAAAAAAAA53908,AAAAAA54032,AAAAA17383,AAAA48949,AAAAAAAAAA18601,AAAAA64669,45449,AAAAAAAAAAA98051,AAAAAAAAAAAAAAAAAA71621}
+47 {98,23,64,12,75,61} {AAA59323,AAAAA95309,AAAAAAAAAAAAAAAA31334,AAAAAAAAA27249,AAAAA17383,AAAAAAAAAAAA37562,AAAAAA1059,A84822,55847,AAAAA70466}
+48 {76,14} {AAAAAAAAAAAAA59671,AAAAAAAAAAAAAAAAAAA91804,AAAAAA66777,AAAAAAAAAAAAAAAAAAA89194,AAAAAAAAAAAAAAA36627,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAA73084,AAAAAAA79710,AAAAAAAAAAAAAAA40402,AAAAAAAAAAAAAAAAAAA65037}
+49 {56,5,54,37,49} {AA21643,AAAAAAAAAAA92631,AAAAAAAA81587}
+50 {20,12,37,64,93} {AAAAAAAAAA5483,AAAAAAAAAAAAAAAAAAA1205,AA6416,AAAAAAAAAAAAAAAAA63050,AAAAAAAAAAAAAAAAAA47955}
+51 {47} {AAAAAAAAAAAAAA96505,AAAAAAAAAAAAAAAAAA36842,AAAAA95309,AAAAAAAA81587,AA6416,AAAA91194,AAAAAA58494,AAAAAA1059,AAAAAAAA69452}
+52 {89,0} {AAAAAAAAAAAAAAAAAA47955,AAAAAAA48038,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAAAAA73084,AAAAA70466,AAAAAAAAAAAAAAAAA764,AAAAAAAAAAA46154,AA66862}
+53 {38,17} {AAAAAAAAAAA21658}
+54 {70,47} {AAAAAAAAAAAAAAAAAA54141,AAAAA40681,AAAAAAA48038,AAAAAAAAAAAAAAAA29150,AAAAA41597,AAAAAAAAAAAAAAAAAA59334,AA15322}
+55 {47,79,47,64,72,25,71,24,93} {AAAAAAAAAAAAAAAAAA55796,AAAAA62737}
+56 {33,7,60,54,93,90,77,85,39} {AAAAAAAAAAAAAAAAAA32918,AA42406}
+57 {23,45,10,42,36,21,9,96} {AAAAAAAAAAAAAAAAAAA70415}
+58 {92} {AAAAAAAAAAAAAAAA98414,AAAAAAAA23648,AAAAAAAAAAAAAAAAAA55796,AA25381,AAAAAAAAAAA6119}
+59 {9,69,46,77} {39557,AAAAAAA89932,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAAAAAAAAA26540,AAA20874,AA6416,AAAAAAAAAAAAAAAAAA47955}
+60 {62,2,59,38,89} {AAAAAAA89932,AAAAAAAAAAAAAAAAAAA15356,AA99927,AA17009,AAAAAAAAAAAAAAA35875}
+61 {72,2,44,95,54,54,13} {AAAAAAAAAAAAAAAAAAA91804}
+62 {83,72,29,73} {AAAAAAAAAAAAA15097,AAAA8857,AAAAAAAAAAAA35809,AAAAAAAAAAAA52814,AAAAAAAAAAAAAAAAAAA38885,AAAAAAAAAAAAAAAAAA24183,AAAAAA43678,A96617}
+63 {11,4,61,87} {AAAAAAAAA27249,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAA13198,AAA20874,39557,51533,AAAAAAAAAAA53908,AAAAAAAAAAAAAA96505,AAAAAAAA78938}
+64 {26,19,34,24,81,78} {A96617,AAAAAAAAAAAAAAAAAAA70104,A68938,AAAAAAAAAAA53908,AAAAAAAAAAAAAAA453,AA17009,AAAAAAA80240}
+65 {61,5,76,59,17} {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012}
+66 {31,23,70,52,4,33,48,25} {AAAAAAAAAAAAAAAAA69675,AAAAAAAA50094,AAAAAAAAAAA92631,AAAA35194,39557,AAAAAAA99836}
+67 {31,94,7,10} {AAAAAA38063,A96617,AAAA35194,AAAAAAAAAAAA67946}
+68 {90,43,38} {AA75092,AAAAAAAAAAAAAAAAA69675,AAAAAAAAAAA92631,AAAAAAAAA10012,AAAAAAAAAAAAA7929,AA21643}
+69 {67,35,99,85,72,86,44} {AAAAAAAAAAAAAAAAAAA1205,AAAAAAAA50094,AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAAAAAAA47955}
+70 {56,70,83} {AAAA41702,AAAAAAAAAAA82945,AA21643,AAAAAAAAAAA99000,A27153,AA25381,AAAAAAAAAAAAAA96505,AAAAAAA1242}
+71 {74,26} {AAAAAAAAAAA50956,AA74433,AAAAAAA21462,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAA36627,AAAAAAAAAAAAA70254,AAAAAAAAAA43419,39557}
+72 {22,1,16,78,20,91,83} {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407}
+73 {88,25,96,78,65,15,29,19} {AAA54451,AAAAAAAAA27249,AAAAAAA9228,AAAAAAAAAAAAAAA67062,AAAAAAAAAAAAAAAAAAA70415,AAAAA17383,AAAAAAAAAAAAAAAA33598}
+74 {32} {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+75 {12,96,83,24,71,89,55} {AAAA48949,AAAAAAAA29716,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAAA67946,AAAAAAAAAAAAAAAA29150,AAA28075,AAAAAAAAAAAAAAAAA43052}
+76 {92,55,10,7} {AAAAAAAAAAAAAAA67062}
+77 {97,15,32,17,55,59,18,37,50,39} {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+78 {55,89,44,84,34} {AAAAAAAAAAA6119,AAAAAAAAAAAAAA8666,AA99927,AA42406,AAAAAAA81898,AAAAAAA9228,AAAAAAAAAAA92631,AA21643,AAAAAAAAAAAAAA28620}
+79 {45} {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+80 {74,89,44,80,0} {AAAA35194,AAAAAAAA79710,AAA20874,AAAAAAAAAAAAAAAAAAA70104,AAAAAAAAAAAAA73084,AAAAAAA57334,AAAAAAA9228,AAAAAAAAAAAAA62007}
+81 {63,77,54,48,61,53,97} {AAAAAAAAAAAAAAA81326,AAAAAAAAAA22292,AA25381,AAAAAAAAAAA74076,AAAAAAA81898,AAAAAAAAA72121}
+82 {34,60,4,79,78,16,86,89,42,50} {AAAAA40681,AAAAAAAAAAAAAAAAAA12591,AAAAAAA80240,AAAAAAAAAAAAAAAA55798,AAAAAAAAAAAAAAAAAAA70104}
+83 {14,10} {AAAAAAAAAA22292,AAAAAAAAAAAAA70254,AAAAAAAAAAA6119}
+84 {11,83,35,13,96,94} {AAAAA95309,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAAAAA24183}
+85 {39,60} {AAAAAAAAAAAAAAAA55798,AAAAAAAAAA22292,AAAAAAA66161,AAAAAAA21462,AAAAAAAAAAAAAAAAAA12591,55847,AAAAAA98232,AAAAAAAAAAA46154}
+86 {33,81,72,74,45,36,82} {AAAAAAAA81587,AAAAAAAAAAAAAA96505,45449,AAAA80176}
+87 {57,27,50,12,97,68} {AAAAAAAAAAAAAAAAA26540,AAAAAAAAA10012,AAAAAAAAAAAA35809,AAAAAAAAAAAAAAAA29150,AAAAAAAAAAA82945,AAAAAA66777,31228,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAA96505}
+88 {41,90,77,24,6,24} {AAAA35194,AAAA35194,AAAAAAA80240,AAAAAAAAAAA46154,AAAAAA58494,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAAA59334,AAAAAAAAAAAAAAAAAAA91804,AA74433}
+89 {40,32,17,6,30,88} {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+90 {88,75} {AAAAA60038,AAAAAAAA23648,AAAAAAAAAAA99000,AAAA41702,AAAAAAAAAAAAA22860,AAAAAAAAAAAAAAA68526}
+91 {78} {AAAAAAAAAAAAA62007,AAA99043}
+92 {85,63,49,45} {AAAAAAA89932,AAAAAAAAAAAAA22860,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAAA21089}
+93 {11} {AAAAAAAAAAA176,AAAAAAAAAAAAAA8666,AAAAAAAAAAAAAAA453,AAAAAAAAAAAAA85723,A68938,AAAAAAAAAAAAA9821,AAAAAAA48038,AAAAAAAAAAAAAAAAA59387,AA99927,AAAAA17383}
+94 {98,9,85,62,88,91,60,61,38,86} {AAAAAAAA81587,AAAAA17383,AAAAAAAA81587}
+95 {47,77} {AAAAAAAAAAAAAAAAA764,AAAAAAAAAAA74076,AAAAAAAAAA18107,AAAAA40681,AAAAAAAAAAAAAAA35875,AAAAA60038,AAAAAAA56483}
+96 {23,97,43} {AAAAAAAAAA646,A87088}
+97 {54,2,86,65} {47735,AAAAAAA99836,AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAA29150,AAAAAAA80240,AAAAAAAAAAAAAAAA98414,AAAAAAA56483,AAAAAAAAAAAAAAAA29150,AAAAAAA39692,AA21643}
+98 {38,34,32,89} {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+99 {37,86} {AAAAAAAAAAAAAAAAAA32918,AAAAA70514,AAAAAAAAA10012,AAAAAAAAAAAAAAAAA59387,AAAAAAAAAA64777,AAAAAAAAAAAAAAAAAAA15356}
+100 {85,32,57,39,49,84,32,3,30} {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523}
{0,1,2,3}
(1 row)
+SELECT * FROM array_op_test WHERE i @ '{32}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+ 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+ 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523}
+(6 rows)
+
+SELECT * FROM array_op_test WHERE i && '{32}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+ 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+ 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523}
+(6 rows)
+
+SELECT * FROM array_op_test WHERE i @ '{17}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576}
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938}
+ 53 | {38,17} | {AAAAAAAAAAA21658}
+ 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+(8 rows)
+
+SELECT * FROM array_op_test WHERE i && '{17}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576}
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938}
+ 53 | {38,17} | {AAAAAAAAAAA21658}
+ 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+(8 rows)
+
+SELECT * FROM array_op_test WHERE i @ '{32,17}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+(3 rows)
+
+SELECT * FROM array_op_test WHERE i && '{32,17}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576}
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938}
+ 53 | {38,17} | {AAAAAAAAAAA21658}
+ 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012}
+ 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+ 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+ 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523}
+(11 rows)
+
+SELECT * FROM array_op_test WHERE i ~ '{38,34,32,89}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------+----------------------------------------------------------------------------------------------------------------------------
+ 40 | {34} | {AAAAAAAAAAAAAA10611,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAA31334,AAAAA70466,AAAAAAAA81587,AAAAAAA74623}
+ 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+ 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+(3 rows)
+
+SELECT * FROM array_op_test WHERE t @ '{AAAAAAAA72908}' ORDER BY seqno;
+ seqno | i | t
+-------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------
+ 22 | {11,6,56,62,53,30} | {AAAAAAAA72908}
+ 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+ 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+(4 rows)
+
+SELECT * FROM array_op_test WHERE t && '{AAAAAAAA72908}' ORDER BY seqno;
+ seqno | i | t
+-------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------
+ 22 | {11,6,56,62,53,30} | {AAAAAAAA72908}
+ 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+ 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+(4 rows)
+
+SELECT * FROM array_op_test WHERE t @ '{AAAAAAAAAA646}' ORDER BY seqno;
+ seqno | i | t
+-------+------------------+--------------------------------------------------------------------
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+ 96 | {23,97,43} | {AAAAAAAAAA646,A87088}
+(3 rows)
+
+SELECT * FROM array_op_test WHERE t && '{AAAAAAAAAA646}' ORDER BY seqno;
+ seqno | i | t
+-------+------------------+--------------------------------------------------------------------
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+ 96 | {23,97,43} | {AAAAAAAAAA646,A87088}
+(3 rows)
+
+SELECT * FROM array_op_test WHERE t @ '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno;
+ seqno | i | t
+-------+------+--------------------------------------------------------------------
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+(1 row)
+
+SELECT * FROM array_op_test WHERE t && '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno;
+ seqno | i | t
+-------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 22 | {11,6,56,62,53,30} | {AAAAAAAA72908}
+ 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+ 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+ 96 | {23,97,43} | {AAAAAAAAAA646,A87088}
+(6 rows)
+
+SELECT * FROM array_op_test WHERE t ~ '{AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}' ORDER BY seqno;
+ seqno | i | t
+-------+--------------------+-----------------------------------------------------------------------------------------------------------
+ 22 | {11,6,56,62,53,30} | {AAAAAAAA72908}
+ 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+(2 rows)
+
-- array casts
SELECT ARRAY[1,2,3]::text[]::int[]::float8[] AS "{1,2,3}";
{1,2,3}
2
(1 row)
+RESET enable_seqscan;
+RESET enable_indexscan;
+RESET enable_bitmapscan;
+--
+-- GIN over int[]
+--
+SET enable_seqscan = OFF;
+SET enable_indexscan = ON;
+SET enable_bitmapscan = ON;
+CREATE INDEX intarrayidx ON array_index_op_test USING gin (i);
+SELECT * FROM array_index_op_test WHERE i @ '{32}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+ 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+ 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523}
+(6 rows)
+
+SELECT * FROM array_index_op_test WHERE i && '{32}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+ 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+ 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523}
+(6 rows)
+
+SELECT * FROM array_index_op_test WHERE i @ '{17}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576}
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938}
+ 53 | {38,17} | {AAAAAAAAAAA21658}
+ 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+(8 rows)
+
+SELECT * FROM array_index_op_test WHERE i && '{17}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576}
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938}
+ 53 | {38,17} | {AAAAAAAAAAA21658}
+ 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+(8 rows)
+
+SELECT * FROM array_index_op_test WHERE i @ '{32,17}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+(3 rows)
+
+SELECT * FROM array_index_op_test WHERE i && '{32,17}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
+ 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657}
+ 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576}
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938}
+ 53 | {38,17} | {AAAAAAAAAAA21658}
+ 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012}
+ 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+ 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066}
+ 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673}
+ 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+ 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523}
+(11 rows)
+
+SELECT * FROM array_index_op_test WHERE i ~ '{38,34,32,89}' ORDER BY seqno;
+ seqno | i | t
+-------+---------------+----------------------------------------------------------------------------------------------------------------------------
+ 40 | {34} | {AAAAAAAAAAAAAA10611,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAA31334,AAAAA70466,AAAAAAAA81587,AAAAAAA74623}
+ 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956}
+ 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845}
+(3 rows)
+
+CREATE INDEX textarrayidx ON array_index_op_test USING gin (t);
+SELECT * FROM array_index_op_test WHERE t @ '{AAAAAAAA72908}' ORDER BY seqno;
+ seqno | i | t
+-------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------
+ 22 | {11,6,56,62,53,30} | {AAAAAAAA72908}
+ 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+ 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+(4 rows)
+
+SELECT * FROM array_index_op_test WHERE t && '{AAAAAAAA72908}' ORDER BY seqno;
+ seqno | i | t
+-------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------
+ 22 | {11,6,56,62,53,30} | {AAAAAAAA72908}
+ 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+ 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+(4 rows)
+
+SELECT * FROM array_index_op_test WHERE t @ '{AAAAAAAAAA646}' ORDER BY seqno;
+ seqno | i | t
+-------+------------------+--------------------------------------------------------------------
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+ 96 | {23,97,43} | {AAAAAAAAAA646,A87088}
+(3 rows)
+
+SELECT * FROM array_index_op_test WHERE t && '{AAAAAAAAAA646}' ORDER BY seqno;
+ seqno | i | t
+-------+------------------+--------------------------------------------------------------------
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+ 96 | {23,97,43} | {AAAAAAAAAA646,A87088}
+(3 rows)
+
+SELECT * FROM array_index_op_test WHERE t @ '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno;
+ seqno | i | t
+-------+------+--------------------------------------------------------------------
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+(1 row)
+
+SELECT * FROM array_index_op_test WHERE t && '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno;
+ seqno | i | t
+-------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------
+ 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309}
+ 22 | {11,6,56,62,53,30} | {AAAAAAAA72908}
+ 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+ 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407}
+ 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908}
+ 96 | {23,97,43} | {AAAAAAAAAA646,A87088}
+(6 rows)
+
+SELECT * FROM array_index_op_test WHERE t ~ '{AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}' ORDER BY seqno;
+ seqno | i | t
+-------+--------------------+-----------------------------------------------------------------------------------------------------------
+ 22 | {11,6,56,62,53,30} | {AAAAAAAA72908}
+ 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}
+(2 rows)
+
RESET enable_seqscan;
RESET enable_indexscan;
RESET enable_bitmapscan;
seqno float8,
random int4
);
+CREATE TABLE array_op_test (
+ seqno int4,
+ i int4[],
+ t text[]
+);
+CREATE TABLE array_index_op_test (
+ seqno int4,
+ i int4[],
+ t text[]
+);
'SELECT ($1 = $2) OR
EXISTS(select 1 from pg_cast where
castsource = $1 and casttarget = $2 and
- castfunc = 0 and castcontext = ''i'')'
+ castfunc = 0 and castcontext = ''i'') OR
+ ( EXISTS(select 1 from pg_type source where
+ source.oid = $1 and source.typelem != 0 )
+ AND
+ EXISTS(select 1 from pg_type target where
+ target.oid = $2 and target.typname = ''anyarray'' ) )'
language sql;
-- This one ignores castcontext, so it considers only physical equivalence
-- and not whether the coercion can be invoked implicitly.
-- Detect missing pg_amop entries: should have as many strategy operators
-- as AM expects for each opclass for the AM. When nondefault subtypes are
-- present, enforce condition separately for each subtype.
--- We have to exclude GiST, unfortunately, since it hasn't got any fixed
+-- We have to exclude GiST and GIN, unfortunately, since its havn't got any fixed
-- requirements about strategy operators.
SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amopsubtype
FROM pg_am AS p1, pg_opclass AS p2, pg_amop AS p3
WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND
- p1.amname != 'gist' AND
+ p1.amname != 'gist' AND p1.amname != 'gin' AND
p1.amstrategies != (SELECT count(*) FROM pg_amop AS p4
WHERE p4.amopclaid = p2.oid AND
p4.amopsubtype = p3.amopsubtype);
783 | 10 | <<|
783 | 11 | |>>
783 | 12 | |&>
-(24 rows)
+ 2742 | 1 | &&
+ 2742 | 2 | @
+ 2742 | 3 | ~
+(27 rows)
-- Check that all operators linked to by opclass entries have selectivity
-- estimators. This is not absolutely required, but it seems a reasonable
ORDER BY relname;
relname | relhasindex
---------------------+-------------
+ array_index_op_test | t
bt_f8_heap | t
bt_i4_heap | t
bt_name_heap | t
shighway | t
tenk1 | t
tenk2 | t
-(59 rows)
+(60 rows)
--
-- another sanity check: every system catalog that has OIDs should have
COPY bt_f8_heap FROM '@abs_srcdir@/data/hash.data';
+COPY array_op_test FROM '@abs_srcdir@/data/array.data';
+
+COPY array_index_op_test FROM '@abs_srcdir@/data/array.data';
+
--- test copying in CSV mode with various styles
--- of embedded line ending characters
COPY bt_name_heap FROM '@abs_srcdir@/data/hash.data';
COPY bt_txt_heap FROM '@abs_srcdir@/data/desc.data';
COPY bt_f8_heap FROM '@abs_srcdir@/data/hash.data';
+COPY array_op_test FROM '@abs_srcdir@/data/array.data';
+COPY array_index_op_test FROM '@abs_srcdir@/data/array.data';
--- test copying in CSV mode with various styles
--- of embedded line ending characters
create temp table copytest (
a_star
abstime_tbl
aggtest
+ array_index_op_test
+ array_op_test
arrtest
b
b_star
toyemp
varchar_tbl
xacttest
-(97 rows)
+(99 rows)
SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer')));
name
SELECT ARRAY[0,0] || ARRAY[1,1] || ARRAY[2,2] AS "{0,0,1,1,2,2}";
SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}";
+SELECT * FROM array_op_test WHERE i @ '{32}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE i && '{32}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE i @ '{17}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE i && '{17}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE i @ '{32,17}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE i && '{32,17}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE i ~ '{38,34,32,89}' ORDER BY seqno;
+
+SELECT * FROM array_op_test WHERE t @ '{AAAAAAAA72908}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE t && '{AAAAAAAA72908}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE t @ '{AAAAAAAAAA646}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE t && '{AAAAAAAAAA646}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE t @ '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE t && '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno;
+SELECT * FROM array_op_test WHERE t ~ '{AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}' ORDER BY seqno;
+
-- array casts
SELECT ARRAY[1,2,3]::text[]::int[]::float8[] AS "{1,2,3}";
SELECT ARRAY[1,2,3]::text[]::int[]::float8[] is of (float8[]) as "TRUE";
SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle;
+RESET enable_seqscan;
+RESET enable_indexscan;
+RESET enable_bitmapscan;
+
+--
+-- GIN over int[]
+--
+
+SET enable_seqscan = OFF;
+SET enable_indexscan = ON;
+SET enable_bitmapscan = ON;
+
+CREATE INDEX intarrayidx ON array_index_op_test USING gin (i);
+
+SELECT * FROM array_index_op_test WHERE i @ '{32}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE i && '{32}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE i @ '{17}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE i && '{17}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE i @ '{32,17}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE i && '{32,17}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE i ~ '{38,34,32,89}' ORDER BY seqno;
+
+CREATE INDEX textarrayidx ON array_index_op_test USING gin (t);
+
+SELECT * FROM array_index_op_test WHERE t @ '{AAAAAAAA72908}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE t && '{AAAAAAAA72908}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE t @ '{AAAAAAAAAA646}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE t && '{AAAAAAAAAA646}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE t @ '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE t && '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno;
+SELECT * FROM array_index_op_test WHERE t ~ '{AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}' ORDER BY seqno;
+
+
RESET enable_seqscan;
RESET enable_indexscan;
RESET enable_bitmapscan;
random int4
);
+CREATE TABLE array_op_test (
+ seqno int4,
+ i int4[],
+ t text[]
+);
+
+CREATE TABLE array_index_op_test (
+ seqno int4,
+ i int4[],
+ t text[]
+);
'SELECT ($1 = $2) OR
EXISTS(select 1 from pg_cast where
castsource = $1 and casttarget = $2 and
- castfunc = 0 and castcontext = ''i'')'
+ castfunc = 0 and castcontext = ''i'') OR
+ ( EXISTS(select 1 from pg_type source where
+ source.oid = $1 and source.typelem != 0 )
+ AND
+ EXISTS(select 1 from pg_type target where
+ target.oid = $2 and target.typname = ''anyarray'' ) )'
language sql;
-- This one ignores castcontext, so it considers only physical equivalence
-- Detect missing pg_amop entries: should have as many strategy operators
-- as AM expects for each opclass for the AM. When nondefault subtypes are
-- present, enforce condition separately for each subtype.
--- We have to exclude GiST, unfortunately, since it hasn't got any fixed
+-- We have to exclude GiST and GIN, unfortunately, since its havn't got any fixed
-- requirements about strategy operators.
SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amopsubtype
FROM pg_am AS p1, pg_opclass AS p2, pg_amop AS p3
WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND
- p1.amname != 'gist' AND
+ p1.amname != 'gist' AND p1.amname != 'gin' AND
p1.amstrategies != (SELECT count(*) FROM pg_amop AS p4
WHERE p4.amopclaid = p2.oid AND
p4.amopsubtype = p3.amopsubtype);