diff --git a/src/ivfflat.c b/src/ivfflat.c index d6383f4..c364da4 100644 --- a/src/ivfflat.c +++ b/src/ivfflat.c @@ -182,6 +182,15 @@ ivfflatvalidate(Oid opclassoid) return true; } +/* + * Checks if index-only scan is supported + */ +static bool +ivfflatcanreturn(Relation index, int attno) +{ + return attno == 1 && IvfflatOptionalProcInfo(index, IVFFLAT_NORM_PROC) == NULL; +} + /* * Define index handler * @@ -223,7 +232,7 @@ ivfflathandler(PG_FUNCTION_ARGS) amroutine->aminsert = ivfflatinsert; amroutine->ambulkdelete = ivfflatbulkdelete; amroutine->amvacuumcleanup = ivfflatvacuumcleanup; - amroutine->amcanreturn = NULL; /* tuple not included in heapsort */ + amroutine->amcanreturn = ivfflatcanreturn; amroutine->amcostestimate = ivfflatcostestimate; amroutine->amoptions = ivfflatoptions; amroutine->amproperty = NULL; /* TODO AMPROP_DISTANCE_ORDERABLE */ diff --git a/src/ivfscan.c b/src/ivfscan.c index 7bd93f0..29a822b 100644 --- a/src/ivfscan.c +++ b/src/ivfscan.c @@ -141,6 +141,7 @@ GetScanItems(IndexScanDesc scan, Datum value) IndexTuple itup; Datum datum; bool isnull; + ItemPointerData indextid; ItemId itemid = PageGetItemId(page, offno); /* Skip dead tuples */ @@ -149,6 +150,7 @@ GetScanItems(IndexScanDesc scan, Datum value) itup = (IndexTuple) PageGetItem(page, itemid); datum = index_getattr(itup, 1, tupdesc, &isnull); + ItemPointerSet(&indextid, searchPage, offno); /* * Add virtual tuple @@ -161,7 +163,7 @@ GetScanItems(IndexScanDesc scan, Datum value) slot->tts_isnull[0] = false; slot->tts_values[1] = PointerGetDatum(&itup->t_tid); slot->tts_isnull[1] = false; - slot->tts_values[2] = Int32GetDatum((int) searchPage); + slot->tts_values[2] = PointerGetDatum(&indextid); slot->tts_isnull[2] = false; ExecStoreVirtualTuple(slot); @@ -280,7 +282,7 @@ ivfflatbeginscan(Relation index, int nkeys, int norderbys) #endif TupleDescInitEntry(so->tupdesc, (AttrNumber) 1, "distance", FLOAT8OID, -1, 0); TupleDescInitEntry(so->tupdesc, (AttrNumber) 2, "heaptid", TIDOID, -1, 0); - TupleDescInitEntry(so->tupdesc, (AttrNumber) 3, "indexblkno", INT4OID, -1, 0); + TupleDescInitEntry(so->tupdesc, (AttrNumber) 3, "indextid", TIDOID, -1, 0); /* Prep sort */ so->sortstate = tuplesort_begin_heap(so->tupdesc, 1, attNums, sortOperators, sortCollations, nullsFirstFlags, work_mem, NULL, false); @@ -295,6 +297,8 @@ ivfflatbeginscan(Relation index, int nkeys, int norderbys) scan->opaque = so; + scan->xs_itupdesc = RelationGetDescr(index); + return scan; } @@ -380,7 +384,7 @@ ivfflatgettuple(IndexScanDesc scan, ScanDirection dir) if (tuplesort_gettupleslot(so->sortstate, true, false, so->slot, NULL)) { ItemPointer heaptid = (ItemPointer) DatumGetPointer(slot_getattr(so->slot, 2, &so->isnull)); - BlockNumber indexblkno = DatumGetInt32(slot_getattr(so->slot, 3, &so->isnull)); + ItemPointer indextid = (ItemPointer) DatumGetPointer(slot_getattr(so->slot, 3, &so->isnull)); #if PG_VERSION_NUM >= 120000 scan->xs_heaptid = *heaptid; @@ -401,7 +405,20 @@ ivfflatgettuple(IndexScanDesc scan, ScanDirection dir) * * https://www.postgresql.org/docs/current/index-locking.html */ - so->buf = ReadBuffer(scan->indexRelation, indexblkno); + so->buf = ReadBuffer(scan->indexRelation, ItemPointerGetBlockNumber(indextid)); + + if (scan->xs_want_itup) + { + Page page; + + LockBuffer(so->buf, BUFFER_LOCK_SHARE); + page = BufferGetPage(so->buf); + + /* TODO Copy tuple to IvfflatScanOpaque */ + scan->xs_itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, ItemPointerGetOffsetNumber(indextid))); + + LockBuffer(so->buf, BUFFER_LOCK_UNLOCK); + } scan->xs_recheckorderby = false; return true;