Skip to content

Commit 6563725

Browse files
committed
Ordering by key works for partial, regular and full scan
1 parent 2ee524b commit 6563725

File tree

7 files changed

+146
-72
lines changed

7 files changed

+146
-72
lines changed

src/btree_rum.c

+32-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,38 @@ rum_##type##_outer_distance(PG_FUNCTION_ARGS) \
322322
PG_GETARG_DATUM(1)); \
323323
break; \
324324
default: \
325-
elog(ERROR, "rum_outer_distance_%s: unknown strategy %u", \
325+
elog(ERROR, "rum_%s_outer_distance: unknown strategy %u", \
326+
#type, strategy); \
327+
} \
328+
\
329+
PG_RETURN_DATUM(diff); \
330+
} \
331+
PG_FUNCTION_INFO_V1(rum_##type##_key_distance); \
332+
Datum \
333+
rum_##type##_key_distance(PG_FUNCTION_ARGS) \
334+
{ \
335+
StrategyNumber strategy = PG_GETARG_UINT16(3); \
336+
Datum diff; \
337+
\
338+
switch (strategy) \
339+
{ \
340+
case RUM_DISTANCE: \
341+
diff = DirectFunctionCall2(rum_##type##_distance, \
342+
PG_GETARG_DATUM(2), \
343+
PG_GETARG_DATUM(4)); \
344+
break; \
345+
case RUM_LEFT_DISTANCE: \
346+
diff = DirectFunctionCall2(rum_##type##_left_distance, \
347+
PG_GETARG_DATUM(2), \
348+
PG_GETARG_DATUM(4)); \
349+
break; \
350+
case RUM_RIGHT_DISTANCE: \
351+
diff = DirectFunctionCall2(rum_##type##_right_distance, \
352+
PG_GETARG_DATUM(2), \
353+
PG_GETARG_DATUM(4)); \
354+
break; \
355+
default: \
356+
elog(ERROR, "rum_%s_key_distance: unknown strategy %u", \
326357
#type, strategy); \
327358
} \
328359
\

src/rum.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,13 @@ extern void rumPrepareDataScan(RumBtree btree, Relation index, OffsetNumber attn
553553

554554
/* rumscan.c */
555555

556+
typedef struct RumScanItem
557+
{
558+
RumItem item;
559+
Datum keyValue;
560+
RumNullCategory keyCategory;
561+
} RumScanItem;
562+
556563
/*
557564
* RumScanKeyData describes a single RUM index qualifier expression.
558565
*
@@ -656,7 +663,7 @@ typedef struct RumScanEntryData
656663
* and additional information here
657664
*/
658665
Tuplesortstate *matchSortstate;
659-
RumItem collectRumItem;
666+
RumScanItem collectRumItem;
660667

661668
/* for full-scan query with order-by */
662669
RumBtreeStack *stack;

src/rum_ts_utils.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1412,7 +1412,7 @@ rum_tsquery_distance(PG_FUNCTION_ARGS)
14121412
bool *check = (bool *) PG_GETARG_POINTER(0);
14131413

14141414
/* RumNullCategory keyCategory = PG_GETARG_CHAR(1); */
1415-
/* Datum key = PG_GETARG_DATUM(2); */
1415+
/* Datum key = PG_GETARG_DATUM(2); */
14161416
TSQuery query = PG_GETARG_TSQUERY(4);
14171417
int nkeys = PG_GETARG_INT32(5);
14181418
Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(6);

src/rumget.c

+85-54
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,34 @@ static void insertScanItem(RumScanOpaque so, bool recheck);
3131
static int scan_entry_cmp(const void *p1, const void *p2, void *arg);
3232
static void entryGetItem(RumState * rumstate, RumScanEntry entry, bool *nextEntryList);
3333

34+
/*
35+
* Extract key value for ordering.
36+
*
37+
* XXX FIXME only pass-by-value!!! Value should be copied to
38+
* long-lived memory context and, somehow, freeed. Seems, the
39+
* last is real problem.
40+
*/
41+
#define SCAN_ENTRY_GET_KEY(entry, rumstate, itup) \
42+
do { \
43+
if ((entry)->useCurKey) \
44+
(entry)->curKey = rumtuple_get_key(rumstate, itup, &(entry)->curKeyCategory); \
45+
} while(0)
46+
47+
/*
48+
* Assign key value for ordering.
49+
*
50+
* XXX FIXME only pass-by-value!!! Value should be copied to
51+
* long-lived memory context and, somehow, freeed. Seems, the
52+
* last is real problem.
53+
*/
54+
#define SCAN_ITEM_PUT_KEY(entry, item, key, category) \
55+
do { \
56+
if ((entry)->useCurKey) \
57+
{ \
58+
(item).keyValue = key; \
59+
(item).keyCategory = category; \
60+
} \
61+
} while(0)
3462

3563
static bool
3664
callAddInfoConsistentFn(RumState * rumstate, RumScanKey key)
@@ -151,23 +179,6 @@ callConsistentFn(RumState * rumstate, RumScanKey key)
151179
return res && callAddInfoConsistentFn(rumstate, key);
152180
}
153181

154-
/*
155-
* Extract key value for ordering
156-
*/
157-
static void
158-
scanEntryGetKey(RumScanEntry entry, RumState *rumstate, IndexTuple itup)
159-
{
160-
if (entry->useCurKey == false)
161-
return;
162-
163-
/*
164-
* XXX FIXME only pass-by-value!!! Value should be copied to
165-
* long-lived memory context and, somehow, freeed. Seems, the
166-
* last is real problem.
167-
*/
168-
entry->curKey = rumtuple_get_key(rumstate, itup, &entry->curKeyCategory);
169-
}
170-
171182
/*
172183
* Goes to the next page if current offset is outside of bounds
173184
*/
@@ -199,7 +210,8 @@ moveRightIfItNeeded(RumBtreeData * btree, RumBtreeStack * stack)
199210
*/
200211
static void
201212
scanPostingTree(Relation index, RumScanEntry scanEntry,
202-
BlockNumber rootPostingTree, OffsetNumber attnum, RumState * rumstate)
213+
BlockNumber rootPostingTree, OffsetNumber attnum,
214+
RumState * rumstate, Datum idatum, RumNullCategory icategory)
203215
{
204216
RumPostingTreeScan *gdi;
205217
Buffer buffer;
@@ -230,15 +242,16 @@ scanPostingTree(Relation index, RumScanEntry scanEntry,
230242
if ((RumPageGetOpaque(page)->flags & RUM_DELETED) == 0 &&
231243
maxoff >= FirstOffsetNumber)
232244
{
233-
RumItem item;
245+
RumScanItem item;
234246
Pointer ptr;
235247

236-
ItemPointerSetMin(&item.iptr);
248+
ItemPointerSetMin(&item.item.iptr);
237249

238250
ptr = RumDataPageGetData(page);
239251
for (i = FirstOffsetNumber; i <= maxoff; i++)
240252
{
241-
ptr = rumDataPageLeafRead(ptr, attnum, &item, rumstate);
253+
ptr = rumDataPageLeafRead(ptr, attnum, &item.item, rumstate);
254+
SCAN_ITEM_PUT_KEY(scanEntry, item, idatum, icategory);
242255
rum_tuplesort_putrumitem(scanEntry->matchSortstate, &item);
243256
}
244257

@@ -387,7 +400,8 @@ collectMatchBitmap(RumBtreeData * btree, RumBtreeStack * stack,
387400
LockBuffer(stack->buffer, RUM_UNLOCK);
388401

389402
/* Collect all the TIDs in this entry's posting tree */
390-
scanPostingTree(btree->index, scanEntry, rootPostingTree, attnum, rumstate);
403+
scanPostingTree(btree->index, scanEntry, rootPostingTree, attnum,
404+
rumstate, idatum, icategory);
391405

392406
/*
393407
* We lock again the entry page and while it was unlocked insert
@@ -437,13 +451,14 @@ collectMatchBitmap(RumBtreeData * btree, RumBtreeStack * stack,
437451
{
438452
int i;
439453
char *ptr = RumGetPosting(itup);
440-
RumItem item;
454+
RumScanItem item;
441455

442-
ItemPointerSetMin(&item.iptr);
456+
ItemPointerSetMin(&item.item.iptr);
443457
for (i = 0; i < RumGetNPosting(itup); i++)
444458
{
445-
ptr = rumDataPageLeafRead(ptr, scanEntry->attnum, &item,
459+
ptr = rumDataPageLeafRead(ptr, scanEntry->attnum, &item.item,
446460
rumstate);
461+
SCAN_ITEM_PUT_KEY(scanEntry, item, idatum, icategory);
447462
rum_tuplesort_putrumitem(scanEntry->matchSortstate, &item);
448463
}
449464

@@ -576,7 +591,7 @@ startScanEntry(RumState * rumstate, RumScanEntry entry)
576591
if (entry->matchSortstate)
577592
{
578593
rum_tuplesort_performsort(entry->matchSortstate);
579-
ItemPointerSetMin(&entry->collectRumItem.iptr);
594+
ItemPointerSetMin(&entry->collectRumItem.item.iptr);
580595
entry->isFinished = FALSE;
581596
}
582597
}
@@ -659,7 +674,7 @@ startScanEntry(RumState * rumstate, RumScanEntry entry)
659674
entry->scanWithAddInfo)
660675
entry->stack = stackEntry;
661676

662-
scanEntryGetKey(entry, rumstate, itup);
677+
SCAN_ENTRY_GET_KEY(entry, rumstate, itup);
663678
}
664679

665680
if (needUnlock)
@@ -1066,7 +1081,7 @@ entryGetNextItemList(RumState * rumstate, RumScanEntry entry)
10661081
entry->curItem = entry->list[entry->offset];
10671082
entry->offset += entry->scanDirection;
10681083

1069-
scanEntryGetKey(entry, rumstate, itup);
1084+
SCAN_ENTRY_GET_KEY(entry, rumstate, itup);
10701085

10711086
/*
10721087
* Done with this entry, go to the next for the future.
@@ -1102,11 +1117,11 @@ entryGetItem(RumState * rumstate, RumScanEntry entry, bool *nextEntryList)
11021117

11031118
do
11041119
{
1105-
RumItem collected;
1106-
RumItem *current_collected;
1120+
RumScanItem collected;
1121+
RumScanItem *current_collected;
11071122

11081123
/* We are finished, but should return last result */
1109-
if (ItemPointerIsMax(&entry->collectRumItem.iptr))
1124+
if (ItemPointerIsMax(&entry->collectRumItem.item.iptr))
11101125
{
11111126
entry->isFinished = TRUE;
11121127
rum_tuplesort_end(entry->matchSortstate);
@@ -1115,10 +1130,10 @@ entryGetItem(RumState * rumstate, RumScanEntry entry, bool *nextEntryList)
11151130
}
11161131

11171132
/* collectRumItem could store the begining of current result */
1118-
if (!ItemPointerIsMin(&entry->collectRumItem.iptr))
1133+
if (!ItemPointerIsMin(&entry->collectRumItem.item.iptr))
11191134
collected = entry->collectRumItem;
11201135
else
1121-
ItemPointerSetMin(&collected.iptr);
1136+
ItemPointerSetMin(&collected.item.iptr);
11221137

11231138
ItemPointerSetMin(&entry->curItem.iptr);
11241139

@@ -1133,60 +1148,76 @@ entryGetItem(RumState * rumstate, RumScanEntry entry, bool *nextEntryList)
11331148

11341149
if (current_collected == NULL)
11351150
{
1136-
entry->curItem = collected;
1151+
entry->curItem = collected.item;
1152+
if (entry->useCurKey)
1153+
{
1154+
entry->curKey = collected.keyValue;
1155+
entry->curKeyCategory = collected.keyCategory;
1156+
}
11371157
break;
11381158
}
11391159

1140-
if (ItemPointerIsMin(&collected.iptr) ||
1141-
rumCompareItemPointers(&collected.iptr,
1142-
&current_collected->iptr) == 0)
1160+
if (ItemPointerIsMin(&collected.item.iptr) ||
1161+
rumCompareItemPointers(&collected.item.iptr,
1162+
&current_collected->item.iptr) == 0)
11431163
{
11441164
Datum joinedAddInfo = (Datum)0;
11451165
bool joinedAddInfoIsNull;
11461166

1147-
if (ItemPointerIsMin(&collected.iptr))
1167+
if (ItemPointerIsMin(&collected.item.iptr))
11481168
{
11491169
joinedAddInfoIsNull = true; /* will change later */
1150-
collected.addInfoIsNull = true;
1170+
collected.item.addInfoIsNull = true;
11511171
}
11521172
else
1153-
joinedAddInfoIsNull = collected.addInfoIsNull ||
1154-
current_collected->addInfoIsNull;
1173+
joinedAddInfoIsNull = collected.item.addInfoIsNull ||
1174+
current_collected->item.addInfoIsNull;
11551175

11561176
if (joinedAddInfoIsNull)
11571177
{
11581178
joinedAddInfoIsNull =
1159-
(collected.addInfoIsNull && current_collected->addInfoIsNull);
1179+
(collected.item.addInfoIsNull &&
1180+
current_collected->item.addInfoIsNull);
11601181

1161-
if (collected.addInfoIsNull == false)
1162-
joinedAddInfo = collected.addInfo;
1163-
else if (current_collected->addInfoIsNull == false)
1164-
joinedAddInfo = current_collected->addInfo;
1182+
if (collected.item.addInfoIsNull == false)
1183+
joinedAddInfo = collected.item.addInfo;
1184+
else if (current_collected->item.addInfoIsNull == false)
1185+
joinedAddInfo = current_collected->item.addInfo;
11651186
}
11661187
else if (rumstate->canJoinAddInfo[entry->attnumOrig - 1])
11671188
{
11681189
joinedAddInfo =
11691190
FunctionCall2(
11701191
&rumstate->joinAddInfoFn[entry->attnumOrig - 1],
1171-
collected.addInfo,
1172-
current_collected->addInfo);
1192+
collected.item.addInfo,
1193+
current_collected->item.addInfo);
11731194
}
11741195
else
11751196
{
1176-
joinedAddInfo = current_collected->addInfo;
1197+
joinedAddInfo = current_collected->item.addInfo;
11771198
}
11781199

1179-
collected.iptr = current_collected->iptr;
1180-
collected.addInfoIsNull = joinedAddInfoIsNull;
1181-
collected.addInfo = joinedAddInfo;
1200+
collected.item.iptr = current_collected->item.iptr;
1201+
collected.item.addInfoIsNull = joinedAddInfoIsNull;
1202+
collected.item.addInfo = joinedAddInfo;
1203+
if (entry->useCurKey)
1204+
{
1205+
collected.keyValue = current_collected->keyValue;
1206+
collected.keyCategory = current_collected->keyCategory;
1207+
}
11821208

11831209
if (should_free)
11841210
pfree(current_collected);
11851211
}
11861212
else
11871213
{
1188-
entry->curItem = collected;
1214+
entry->curItem = collected.item;
11891215
entry->collectRumItem = *current_collected;
1216+
if (entry->useCurKey)
1217+
{
1218+
entry->curKey = collected.keyValue;
1219+
entry->curKeyCategory = collected.keyCategory;
1220+
}
11901221
if (should_free)
11911222
pfree(current_collected);
11921223
break;
@@ -1196,7 +1227,7 @@ entryGetItem(RumState * rumstate, RumScanEntry entry, bool *nextEntryList)
11961227
if (current_collected == NULL)
11971228
{
11981229
/* mark next call as last */
1199-
ItemPointerSetMax(&entry->collectRumItem.iptr);
1230+
ItemPointerSetMax(&entry->collectRumItem.item.iptr);
12001231

12011232
/* even current call is last */
12021233
if (ItemPointerIsMin(&entry->curItem.iptr))

src/rumscan.c

+8-4
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,19 @@ rumFillScanKey(RumScanOpaque so, OffsetNumber attnum,
169169

170170
if (key->orderBy)
171171
{
172+
if (key->attnum != rumstate->attrnAttachColumn)
173+
key->useCurKey = rumstate->canOrdering[attnum - 1] &&
174+
(strategy == RUM_DISTANCE || strategy == RUM_LEFT_DISTANCE ||
175+
strategy == RUM_RIGHT_DISTANCE);
176+
172177
/* Add key to order by additional information... */
173178
if (key->attnum == rumstate->attrnAttachColumn ||
174179
/* ...add key to order by index key value */
175-
(strategy == RUM_DISTANCE && rumstate->canOrdering[attnum - 1]))
180+
key->useCurKey)
176181
{
177182
if (nQueryValues != 1)
178183
elog(ERROR, "extractQuery should return only one value for ordering");
179-
if (rumstate->origTupdesc->attrs[rumstate->attrnAttachColumn - 1]->attbyval == false)
184+
if (rumstate->origTupdesc->attrs[key->attnum - 1]->attbyval == false)
180185
elog(ERROR, "doesn't support order by over pass-by-reference column");
181186

182187
if (key->attnum == rumstate->attrnAttachColumn)
@@ -188,7 +193,7 @@ rumFillScanKey(RumScanOpaque so, OffsetNumber attnum,
188193
key->outerAddInfoIsNull = true;
189194
key->attnum = rumstate->attrnAddToColumn;
190195
}
191-
else if (strategy == RUM_DISTANCE && rumstate->canOrdering[attnum - 1])
196+
else if (key->useCurKey)
192197
{
193198
RumScanKey scanKey = NULL;
194199

@@ -202,7 +207,6 @@ rumFillScanKey(RumScanOpaque so, OffsetNumber attnum,
202207
}
203208
}
204209

205-
elog(INFO, "test");
206210
if (scanKey == NULL)
207211
elog(ERROR, "cannot order without attribute %d in WHERE clause",
208212
key->attnum);

0 commit comments

Comments
 (0)