#endif
#include "access/heapam.h"
#include "catalog/index.h"
+#if PG_VERSION_NUM >= 90600
+#include <catalog/pg_am.h>
+#endif
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "catalog/namespace.h"
#if PG_VERSION_NUM >= 80300
#include <tsearch/ts_utils.h>
#endif
+#if PG_VERSION_NUM >= 100000
+#include <utils/regproc.h>
+#include <utils/varlena.h>
+#endif
#include <utils/tqual.h>
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include <access/relscan.h>
-#define PAGESIZE (BLCKSZ - MAXALIGN(sizeof(PageHeaderData) + sizeof(ItemIdData)))
+#define PAGESIZE (BLCKSZ - MAXALIGN(sizeof(PageHeaderData) + sizeof(ItemIdData)))
#ifndef PG_NARGS
#define PG_NARGS() (fcinfo->nargs)
#endif
#if PG_VERSION_NUM >= 90600
-#define ISNULL true
+#define ISNULL true
#define ISNOTNULL false
#define heap_formtuple heap_form_tuple
#else
int maxlevel;
text *txt;
char *ptr;
- int len;
+ int len;
} IdxInfo;
static Relation checkOpenedRelation(Relation r, Oid PgAmOid);
static Relation
checkOpenedRelation(Relation r, Oid PgAmOid) {
- if ( r->rd_am == NULL )
+ if ( r->rd_index == NULL )
elog(ERROR, "Relation %s.%s is not an index",
get_namespace_name(RelationGetNamespace(r)),
RelationGetRelationName(r)
}
typedef struct {
- int level;
- int numpages;
- int numleafpages;
- int numtuple;
- int numinvalidtuple;
- int numleaftuple;
+ int level;
+ int numpages;
+ int numleafpages;
+ int numtuple;
+ int numinvalidtuple;
+ int numleaftuple;
uint64 tuplesize;
uint64 leaftuplesize;
uint64 totalsize;
return ( (TypeStorage*)(funcctx->user_fctx) )->item;
}
+#if PG_VERSION_NUM >= 110000
+#define TS_GET_TYPEVAL(s, i, v) (s)->index->rd_att->attrs[(i)].v
+#else
+#define TS_GET_TYPEVAL(s, i, v) (s)->index->rd_att->attrs[(i)]->v
+#endif
+
static void
setup_firstcall(FuncCallContext *funcctx, text *name) {
MemoryContext oldcontext;
tupdesc,
i+3,
attname,
- st->index->rd_att->attrs[i]->atttypid,
- st->index->rd_att->attrs[i]->atttypmod,
- st->index->rd_att->attrs[i]->attndims
+ TS_GET_TYPEVAL(st, i, atttypid),
+ TS_GET_TYPEVAL(st, i, atttypmod),
+ TS_GET_TYPEVAL(st, i, attndims)
);
}
st->dvalues = (Datum *) palloc((tupdesc->natts+2) * sizeof(Datum));
- st->nulls = (char *) palloc((tupdesc->natts+2) * sizeof(*st->nulls));
+ st->nulls = palloc((tupdesc->natts+2) * sizeof(*st->nulls));
funcctx->slot = TupleDescGetSlot(tupdesc);
funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
GinNullCategory category;
#endif
Datum dvalues[2];
+#if PG_VERSION_NUM >= 110000
+ bool nulls[2];
+#else
char nulls[2];
+#endif
} GinStatState;
static bool
}
for(;;) {
- int cmp;
+ int cmp;
#if PG_VERSION_NUM >= 90100
GinNullCategory category;
#elif PG_VERSION_NUM < 80400
bool isnull = false;
#endif
Datum datum;
- IndexTuple itup;
+ IndexTuple itup;
if (moveRightIfItNeeded(st)==false)
return false;
#endif
if ( cmp == 0 )
{
- if ( !st->index->rd_att->attrs[st->attnum]->attbyval )
+ if ( st->curval && !TS_GET_TYPEVAL(st, st->attnum, attbyval) )
pfree( (void*) st->curval );
return true;
}
tupdesc = CreateTemplateTupleDesc(2, false);
TupleDescInitEntry(tupdesc, 1, "value",
- st->index->rd_att->attrs[st->attnum]->atttypid,
- st->index->rd_att->attrs[st->attnum]->atttypmod,
- st->index->rd_att->attrs[st->attnum]->attndims);
+ TS_GET_TYPEVAL(st, st->attnum, atttypid),
+ TS_GET_TYPEVAL(st, st->attnum, atttypmod),
+ TS_GET_TYPEVAL(st, st->attnum, attndims));
TupleDescInitEntry(tupdesc, 2, "nrow", INT4OID, -1, 0);
memset( st->nulls, ISNOTNULL, 2*sizeof(*st->nulls) );
static void
processTuple( FuncCallContext *funcctx, GinStatState *st, IndexTuple itup ) {
- MemoryContext oldcontext;
-#if PG_VERSION_NUM < 80400
+ MemoryContext oldcontext;
+#if PG_VERSION_NUM >= 90100
+ Datum key;
+#elif PG_VERSION_NUM < 80400
bool isnull;
#endif
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+#if PG_VERSION_NUM >= 90100
+ key = gintuple_get_key(&st->ginstate, itup, &st->category);
+
+ if (st->category != GIN_CAT_NORM_KEY)
+ st->curval = (Datum)0;
+ else
+#endif
st->curval = datumCopy(
#if PG_VERSION_NUM >= 90100
- gintuple_get_key(&st->ginstate, itup, &st->category),
+ key,
#elif PG_VERSION_NUM >= 80400
gin_index_getattr(&st->ginstate, itup),
#else
index_getattr(itup, FirstOffsetNumber, st->ginstate.tupdesc, &isnull),
#endif
- st->index->rd_att->attrs[st->attnum]->attbyval,
- st->index->rd_att->attrs[st->attnum]->attlen );
+ TS_GET_TYPEVAL(st, st->attnum, attbyval),
+ TS_GET_TYPEVAL(st, st->attnum, attlen));
MemoryContextSwitchTo(oldcontext);
st->dvalues[0] = st->curval;
ItemPointer list;
#else
GinPostingTreeScan *gdi;
- Buffer entrybuffer;
+ Buffer entrybuffer;
#endif
Page page;
uint32 predictNumber;
LockBuffer(st->buffer, GIN_UNLOCK);
#if PG_VERSION_NUM >= 90400
- stack = ginScanBeginPostingTree(&btree, st->index, rootblkno);
+ stack = ginScanBeginPostingTree(&btree, st->index, rootblkno
+#if PG_VERSION_NUM >= 90600
+ , NULL
+#endif
+ );
page = BufferGetPage(stack->buffer);
ItemPointerSetMin(&minItem);
list = GinDataLeafPageGetItems(page, &nlist, minItem);
pfree(list);
predictNumber = stack->predictNumber;
+ st->dvalues[1] = Int32GetDatum( predictNumber * nlist );
#elif PG_VERSION_NUM >= 90100
gdi = ginPrepareScanPostingTree(st->index, rootblkno, TRUE);
entrybuffer = ginScanBeginPostingTree(gdi);
page = BufferGetPage(entrybuffer);
predictNumber = gdi->stack->predictNumber;
+ st->dvalues[1] = Int32GetDatum( predictNumber * GinPageGetOpaque(page)->maxoff );
#else
gdi = prepareScanPostingTree(st->index, rootblkno, TRUE);
entrybuffer = scanBeginPostingTree(gdi);
page = BufferGetPage(entrybuffer);
predictNumber = gdi->stack->predictNumber;
-#endif
-
st->dvalues[1] = Int32GetDatum( predictNumber * GinPageGetOpaque(page)->maxoff );
+#endif
#if PG_VERSION_NUM < 90400
LockBuffer(entrybuffer, GIN_UNLOCK);
#if PG_VERSION_NUM >= 80300
Datum
gin_count_estimate(PG_FUNCTION_ARGS) {
- text *name=PG_GETARG_TEXT_P(0);
- Relation index;
+ text *name=PG_GETARG_TEXT_P(0);
+ Relation index;
IndexScanDesc scan;
int64 count = 0;
- char *relname=t2c(name);
+ char *relname=t2c(name);
ScanKeyData key;
#if PG_VERSION_NUM >= 80400
- TIDBitmap *bitmap = tbm_create(work_mem * 1024L);
+ TIDBitmap *bitmap = tbm_create(work_mem * 1024L
+#if PG_VERSION_NUM >= 100000
+ , NULL
+#endif
+ );
#else
#define MAXTIDS 1024
ItemPointerData tids[MAXTIDS];
elog(ERROR, "Column type is not a tsvector");
}
- key.sk_flags = 0;
- key.sk_attno = 1;
+ key.sk_flags = 0;
+ key.sk_attno = 1;
key.sk_strategy = TSearchStrategyNumber;
key.sk_subtype = 0;
key.sk_argument = PG_GETARG_DATUM(1);
usedSpace / 1024.0,
usedInnerSpace / 1024.0,
usedLeafSpace / 1024.0,
- (((double) bufferSize) * ((double) totalPages) - usedSpace) / 1024,
- 100.0 * (usedSpace / (((double) bufferSize) * ((double) totalPages))),
+ (((double) bufferSize) * ((double) totalPages) - usedSpace) / 1024,
+ 100.0 * (usedSpace / (((double) bufferSize) * ((double) totalPages))),
leafTuples, innerTuples, nAllTheSame,
nLeafPlaceholder, nInnerPlaceholder,
nLeafRedirect, nInnerRedirect);
#if PG_VERSION_NUM >= 90200
typedef struct SPGistPrintStackElem {
- ItemPointerData iptr;
+ ItemPointerData iptr;
int16 nlabel;
int level;
} SPGistPrintStackElem;
typedef struct SPGistPrint {
SpGistState state;
- Relation index;
- Datum dvalues[7 /* see CreateTemplateTupleDesc call */];
- char nulls[7 /* see CreateTemplateTupleDesc call */];
+ Relation index;
+ Datum dvalues[8 /* see CreateTemplateTupleDesc call */];
+#if PG_VERSION_NUM >= 110000
+ bool nulls[8];
+#else
+ char nulls[8];
+#endif
List *stack;
} SPGistPrint;
MemoryContext oldcontext;
if (SRF_IS_FIRSTCALL()) {
- text *name=PG_GETARG_TEXT_P(0);
- RangeVar *relvar;
+ text *name=PG_GETARG_TEXT_P(0);
+ RangeVar *relvar;
Relation index;
ItemPointerData ipd;
TupleDesc tupdesc;
prst->index = index;
initSpGistState(&prst->state, index);
- tupdesc = CreateTemplateTupleDesc(3 /* types */ + 1 /* level */ + 1 /* nlabel */ + 2 /* tids */, false);
+ tupdesc = CreateTemplateTupleDesc(3 /* types */ + 1 /* level */ + 1 /* nlabel */ + 2 /* tids */ + 1, false);
TupleDescInitEntry(tupdesc, 1, "tid", TIDOID, -1, 0);
- TupleDescInitEntry(tupdesc, 2, "node", INT4OID, -1, 0);
- TupleDescInitEntry(tupdesc, 3, "level", INT4OID, -1, 0);
- TupleDescInitEntry(tupdesc, 4, "tid_pointer", TIDOID, -1, 0);
- TupleDescInitEntry(tupdesc, 5, "prefix",
+ TupleDescInitEntry(tupdesc, 2, "allthesame", BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, 3, "node", INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, 4, "level", INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, 5, "tid_pointer", TIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, 6, "prefix",
(prst->state.attPrefixType.type == VOIDOID) ? INT4OID : prst->state.attPrefixType.type, -1, 0);
- TupleDescInitEntry(tupdesc, 6, "label",
+ TupleDescInitEntry(tupdesc, 7, "label",
(prst->state.attLabelType.type == VOIDOID) ? INT4OID : prst->state.attLabelType.type, -1, 0);
- TupleDescInitEntry(tupdesc, 7, "leaf",
+ TupleDescInitEntry(tupdesc, 8, "leaf",
(prst->state.attType.type == VOIDOID) ? INT4OID : prst->state.attType.type, -1, 0);
funcctx->slot = TupleDescGetSlot(tupdesc);
prst->dvalues[0] = PointerGetDatum(tid);
prst->nulls[0] = ISNOTNULL;
prst->nulls[1] = ISNULL;
- prst->dvalues[2] = s->level;
- prst->nulls[2] = ISNOTNULL;
- prst->nulls[3] = ISNULL;
+ prst->nulls[2] = ISNULL;
+ prst->dvalues[3] = s->level;
+ prst->nulls[3] = ISNOTNULL;
prst->nulls[4] = ISNULL;
prst->nulls[5] = ISNULL;
- prst->dvalues[6] = datumCopy(SGLTDATUM(leafTuple, &prst->state),
+ prst->nulls[6] = ISNULL;
+ prst->dvalues[7] = datumCopy(SGLTDATUM(leafTuple, &prst->state),
prst->state.attType.attbyval, prst->state.attType.attlen);
- prst->nulls[6] = ISNOTNULL;
+ prst->nulls[7] = ISNOTNULL;
} else {
SpGistInnerTuple innerTuple = (SpGistInnerTuple)dtuple;
- int i;
+ int i;
SpGistNodeTuple node;
SGITITERATE(innerTuple, i, node) {
*tid = s->iptr;
prst->dvalues[0] = PointerGetDatum(tid);
prst->nulls[0] = ISNOTNULL;
- prst->dvalues[1] = Int32GetDatum(s->nlabel);
+ prst->dvalues[1] = innerTuple->allTheSame;
prst->nulls[1] = ISNOTNULL;
- prst->dvalues[2] = s->level;
+ prst->dvalues[2] = Int32GetDatum(s->nlabel);
prst->nulls[2] = ISNOTNULL;
+ prst->dvalues[3] = s->level;
+ prst->nulls[3] = ISNOTNULL;
tid = palloc(sizeof(ItemPointerData));
*tid = node->t_tid;
- prst->dvalues[3] = PointerGetDatum(tid);
- prst->nulls[3] = ISNOTNULL;
+ prst->dvalues[4] = PointerGetDatum(tid);
+ prst->nulls[5] = ISNOTNULL;
if (innerTuple->prefixSize > 0) {
- prst->dvalues[4] = datumCopy(SGITDATUM(innerTuple, &prst->state),
+ prst->dvalues[5] = datumCopy(SGITDATUM(innerTuple, &prst->state),
prst->state.attPrefixType.attbyval, prst->state.attPrefixType.attlen);
- prst->nulls[4] = ISNOTNULL;
+ prst->nulls[5] = ISNOTNULL;
} else
- prst->nulls[4] = ISNULL;
+ prst->nulls[5] = ISNULL;
if (!IndexTupleHasNulls(node)) {
- prst->dvalues[5] = datumCopy(SGNTDATUM(node, &prst->state),
+ prst->dvalues[6] = datumCopy(SGNTDATUM(node, &prst->state),
prst->state.attLabelType.attbyval, prst->state.attLabelType.attlen);
- prst->nulls[5] = ISNOTNULL;
+ prst->nulls[6] = ISNOTNULL;
} else
- prst->nulls[5] = ISNULL;
- prst->nulls[6] = ISNULL;
+ prst->nulls[6] = ISNULL;
+ prst->nulls[7] = ISNULL;
pushSPGistPrint(funcctx, prst, &node->t_tid, s->level + 1);
s->nlabel = i + 1;
BlockNumber blkno;
char res[1024];
uint32 totalPages,
+#if PG_VERSION_NUM >= 100000
+ deletedPages = 0,
+ emptyDataPages = 0,
+#endif
entryPages = 0,
dataPages = 0,
dataInnerPages = 0,
page = BufferGetPage(buffer);
header = (PageHeader)page;
+#if PG_VERSION_NUM >= 100000
+ if (GinPageIsDeleted(page))
+ {
+ deletedPages++;
+ }
+ else
+#endif
if (GinPageIsData(page))
{
dataPages++;
if (GinPageIsLeaf(page))
{
- ItemPointerData minItem;
+ ItemPointerData minItem, *ptr;
int nlist;
+
dataLeafPages++;
dataLeafFreeSpace += header->pd_upper - header->pd_lower;
ItemPointerSetMin(&minItem);
- pfree(GinDataLeafPageGetItems(page, &nlist, minItem));
- dataLeafIptrsCount += nlist;
+
+ ptr = GinDataLeafPageGetItems(page, &nlist, minItem);
+
+ if (ptr)
+ {
+ pfree(ptr);
+ dataLeafIptrsCount += nlist;
+ }
+ else
+ emptyDataPages++;
}
else
{
snprintf(res, sizeof(res),
"totalPages: %u\n"
+#if PG_VERSION_NUM >= 100000
+ "deletedPages: %u\n"
+ "emptyDataPages: %u\n"
+#endif
"dataPages: %u\n"
"dataInnerPages: %u\n"
"dataLeafPages: %u\n"
"entryAttrSize: " INT64_FORMAT "\n"
,
totalPages,
+#if PG_VERSION_NUM >= 100000
+ deletedPages,
+ emptyDataPages,
+#endif
dataPages,
dataInnerPages,
dataLeafPages,