Kouhei Sutou
null+****@clear*****
Fri Feb 6 00:17:31 JST 2015
Kouhei Sutou 2015-02-06 00:17:31 +0900 (Fri, 06 Feb 2015) New Revision: f7a0868a3bbc05ffc857ef84f5552e3b23272f5d https://github.com/pgroonga/pgroonga/commit/f7a0868a3bbc05ffc857ef84f5552e3b23272f5d Message: Support ORDER BY LIMIT Added files: expected/compare/integer/order_by_limit/asc.out sql/compare/integer/order_by_limit/asc.sql Modified files: Makefile pgroonga.c test.sql Modified: Makefile (+3 -0) =================================================================== --- Makefile 2015-02-06 00:06:30 +0900 (8e1fbe2) +++ Makefile 2015-02-06 00:17:31 +0900 (9159528) @@ -33,6 +33,7 @@ installcheck: results/full-text-search/text/options/tokenizer installcheck: results/full-text-search/text/options/normalizer installcheck: results/compare/text/single/equal installcheck: results/compare/integer/single/less-than-equal +installcheck: results/compare/integer/order_by_limit results/full-text-search/text/single/contain: @mkdir -p $@ @@ -50,3 +51,5 @@ results/compare/text/single/equal: @mkdir -p $@ results/compare/integer/single/less-than-equal: @mkdir -p $@ +results/compare/integer/order_by_limit: + @mkdir -p $@ Added: expected/compare/integer/order_by_limit/asc.out (+30 -0) 100644 =================================================================== --- /dev/null +++ expected/compare/integer/order_by_limit/asc.out 2015-02-06 00:17:31 +0900 (3e51cc0) @@ -0,0 +1,30 @@ +CREATE TABLE ids ( + id integer +); +INSERT INTO ids VALUES (2); +INSERT INTO ids VALUES (7); +INSERT INTO ids VALUES (6); +INSERT INTO ids VALUES (4); +INSERT INTO ids VALUES (5); +INSERT INTO ids VALUES (8); +INSERT INTO ids VALUES (1); +INSERT INTO ids VALUES (10); +INSERT INTO ids VALUES (3); +INSERT INTO ids VALUES (9); +CREATE INDEX grnindex ON ids USING pgroonga (id); +SET enable_seqscan = off; +SET enable_indexscan = on; +SELECT id + FROM ids + ORDER BY id ASC + LIMIT 5; + id +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +DROP TABLE ids; Modified: pgroonga.c (+177 -30) =================================================================== --- pgroonga.c 2015-02-06 00:06:30 +0900 (3eee473) +++ pgroonga.c 2015-02-06 00:17:31 +0900 (fb3a7db) @@ -44,10 +44,13 @@ typedef PGrnBuildStateData *PGrnBuildState; typedef struct PGrnScanOpaqueData { grn_obj *idsTable; + grn_obj *lexicon; + grn_obj *indexColumn; grn_obj *searched; grn_obj *sorted; grn_obj *targetTable; - grn_table_cursor *cursor; + grn_obj *indexCursor; + grn_table_cursor *tableCursor; grn_obj *keyAccessor; grn_id currentID; } PGrnScanOpaqueData; @@ -424,6 +427,17 @@ PGrnCreateColumn(grn_obj *table, return column; } +static bool +PGrnIsForFullTextSearchIndex(Relation index) +{ + Oid containStrategyOID; + containStrategyOID = get_opfamily_member(index->rd_opfamily[0], + index->rd_opcintype[0], + index->rd_opcintype[0], + PGrnContainStrategyNumber); + return (containStrategyOID != InvalidOid); +} + /** * PGrnCreate * @@ -486,14 +500,7 @@ PGrnCreate(Relation index, grn_obj **idsTable, grn_ctx_at(ctx, attributeTypeID)); } - { - Oid containStrategyOID; - containStrategyOID = get_opfamily_member(index->rd_opfamily[0], - index->rd_opcintype[0], - index->rd_opcintype[0], - PGrnContainStrategyNumber); - forFullTextSearch = (containStrategyOID != InvalidOid); - } + forFullTextSearch = PGrnIsForFullTextSearchIndex(index); switch (typeID) { @@ -734,10 +741,13 @@ static void PGrnScanOpaqueInit(PGrnScanOpaque so, Relation index) { so->idsTable = PGrnLookupIDsTable(index, ERROR); + so->indexColumn = PGrnLookupIndexColumn(index, ERROR); + so->lexicon = grn_column_table(ctx, so->indexColumn); so->searched = NULL; so->sorted = NULL; so->targetTable = NULL; - so->cursor = NULL; + so->indexCursor = NULL; + so->tableCursor = NULL; so->keyAccessor = NULL; so->currentID = GRN_ID_NIL; } @@ -751,10 +761,15 @@ PGrnScanOpaqueReinit(PGrnScanOpaque so) grn_obj_unlink(ctx, so->keyAccessor); so->keyAccessor = NULL; } - if (so->cursor) + if (so->indexCursor) { - grn_table_cursor_close(ctx, so->cursor); - so->cursor = NULL; + grn_obj_close(ctx, so->indexCursor); + so->indexCursor = NULL; + } + if (so->tableCursor) + { + grn_table_cursor_close(ctx, so->tableCursor); + so->tableCursor = NULL; } if (so->sorted) { @@ -958,7 +973,7 @@ PGrnSort(IndexScanDesc scan) } static void -PGrnOpenCursor(IndexScanDesc scan, ScanDirection dir) +PGrnOpenTableCursor(IndexScanDesc scan, ScanDirection dir) { PGrnScanOpaque so = (PGrnScanOpaque) scan->opaque; grn_obj *table; @@ -977,25 +992,125 @@ PGrnOpenCursor(IndexScanDesc scan, ScanDirection dir) else flags |= GRN_CURSOR_ASCENDING; - so->cursor = grn_table_cursor_open(ctx, table, - NULL, 0, NULL, 0, - offset, limit, flags); + so->tableCursor = grn_table_cursor_open(ctx, table, + NULL, 0, NULL, 0, + offset, limit, flags); so->keyAccessor = grn_obj_column(ctx, table, GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_KEY_LEN); } static void +PGrnFillBorder(IndexScanDesc scan, + void **min, unsigned int *minSize, + void **max, unsigned int *maxSize, + int *flags) +{ + Relation index = scan->indexRelation; + int i; + + for (i = 0; i < scan->numberOfKeys; i++) + { + ScanKey key = &(scan->keyData[i]); + + /* TODO: Use buffer for min and max */ + grn_obj_reinit(ctx, &buffer, PGrnGetType(index, key->sk_attno - 1), 0); + PGrnGetValue(index, key->sk_attno - 1, &buffer, key->sk_argument); + + switch (key->sk_strategy) + { + case PGrnLessStrategyNumber: + *max = GRN_BULK_HEAD(&buffer); + *maxSize = GRN_BULK_VSIZE(&buffer); + *flags |= GRN_CURSOR_LT; + break; + case PGrnLessEqualStrategyNumber: + *max = GRN_BULK_HEAD(&buffer); + *maxSize = GRN_BULK_VSIZE(&buffer); + *flags |= GRN_CURSOR_LE; + break; + case PGrnEqualStrategyNumber: + *min = GRN_BULK_HEAD(&buffer); + *minSize = GRN_BULK_VSIZE(&buffer); + *max = GRN_BULK_HEAD(&buffer); + *maxSize = GRN_BULK_VSIZE(&buffer); + *flags |= GRN_CURSOR_LE | GRN_CURSOR_GE; + break; + case PGrnGreaterEqualStrategyNumber: + *min = GRN_BULK_HEAD(&buffer); + *minSize = GRN_BULK_VSIZE(&buffer); + *flags |= GRN_CURSOR_GE; + break; + case PGrnGreaterStrategyNumber: + *min = GRN_BULK_HEAD(&buffer); + *minSize = GRN_BULK_VSIZE(&buffer); + *flags |= GRN_CURSOR_GT; + break; + case PGrnNotEqualStrategyNumber: + /* TODO */ + break; + } + } +} + +static void +PGrnOpenIndexCursor(IndexScanDesc scan, ScanDirection dir) +{ + PGrnScanOpaque so = (PGrnScanOpaque) scan->opaque; + void *min = NULL; + unsigned int minSize = 0; + void *max = NULL; + unsigned int maxSize = 0; + int offset = 0; + int limit = -1; + int flags = 0; + grn_id indexCursorMin = GRN_ID_NIL; + grn_id indexCursorMax = GRN_ID_MAX; + int indexCursorFlags = 0; + + PGrnFillBorder(scan, &min, &minSize, &max, &maxSize, &flags); + + if (dir == BackwardScanDirection) + flags |= GRN_CURSOR_DESCENDING; + else + flags |= GRN_CURSOR_ASCENDING; + + so->tableCursor = grn_table_cursor_open(ctx, so->lexicon, + min, minSize, + max, maxSize, + offset, limit, flags); + so->indexCursor = grn_index_cursor_open(ctx, + so->tableCursor, so->indexColumn, + indexCursorMin, + indexCursorMax, + indexCursorFlags); + so->keyAccessor = grn_obj_column(ctx, so->idsTable, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); +} + +static void PGrnEnsureCursorOpened(IndexScanDesc scan, ScanDirection dir) { PGrnScanOpaque so = (PGrnScanOpaque) scan->opaque; + bool forFullTextSearch = false; - if (so->cursor) + if (so->indexCursor) + return; + if (so->tableCursor) return; - PGrnSearch(scan); - PGrnSort(scan); - PGrnOpenCursor(scan, dir); + forFullTextSearch = PGrnIsForFullTextSearchIndex(scan->indexRelation); + if (forFullTextSearch) + { + PGrnSearch(scan); + PGrnSort(scan); + PGrnOpenTableCursor(scan, dir); + } + else + { + PGrnOpenIndexCursor(scan, dir); + } } @@ -1023,7 +1138,21 @@ pgroonga_gettuple(PG_FUNCTION_ARGS) GRN_OBJ_FIN(ctx, &key); } - so->currentID = grn_table_cursor_next(ctx, so->cursor); + if (so->indexCursor) + { + grn_posting *posting; + grn_id termID; + grn_id id = GRN_ID_NIL; + posting = grn_index_cursor_next(ctx, so->indexCursor, &termID); + if (posting) + id = posting->rid; + so->currentID = id; + } + else + { + so->currentID = grn_table_cursor_next(ctx, so->tableCursor); + } + if (so->currentID == GRN_ID_NIL) { PG_RETURN_BOOL(false); @@ -1052,19 +1181,37 @@ pgroonga_getbitmap(PG_FUNCTION_ARGS) TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1); PGrnScanOpaque so = (PGrnScanOpaque) scan->opaque; int64 nRecords = 0; - grn_id id; grn_obj key; PGrnEnsureCursorOpened(scan, ForwardScanDirection); GRN_UINT64_INIT(&key, 0); - while ((id = grn_table_cursor_next(ctx, so->cursor)) != GRN_ID_NIL) { - ItemPointerData ctid; - GRN_BULK_REWIND(&key); - grn_obj_get_value(ctx, so->keyAccessor, id, &key); - ctid = UInt64ToCtid(GRN_UINT64_VALUE(&key)); - tbm_add_tuples(tbm, &ctid, 1, false); - nRecords++; + if (so->indexCursor) + { + grn_posting *posting; + grn_id termID; + while ((posting = grn_index_cursor_next(ctx, so->indexCursor, &termID))) + { + ItemPointerData ctid; + GRN_BULK_REWIND(&key); + grn_obj_get_value(ctx, so->keyAccessor, posting->rid, &key); + ctid = UInt64ToCtid(GRN_UINT64_VALUE(&key)); + tbm_add_tuples(tbm, &ctid, 1, false); + nRecords++; + } + } + else + { + grn_id id; + while ((id = grn_table_cursor_next(ctx, so->tableCursor)) != GRN_ID_NIL) + { + ItemPointerData ctid; + GRN_BULK_REWIND(&key); + grn_obj_get_value(ctx, so->keyAccessor, id, &key); + ctid = UInt64ToCtid(GRN_UINT64_VALUE(&key)); + tbm_add_tuples(tbm, &ctid, 1, false); + nRecords++; + } } GRN_OBJ_FIN(ctx, &key); Added: sql/compare/integer/order_by_limit/asc.sql (+26 -0) 100644 =================================================================== --- /dev/null +++ sql/compare/integer/order_by_limit/asc.sql 2015-02-06 00:17:31 +0900 (71954e6) @@ -0,0 +1,26 @@ +CREATE TABLE ids ( + id integer +); + +INSERT INTO ids VALUES (2); +INSERT INTO ids VALUES (7); +INSERT INTO ids VALUES (6); +INSERT INTO ids VALUES (4); +INSERT INTO ids VALUES (5); +INSERT INTO ids VALUES (8); +INSERT INTO ids VALUES (1); +INSERT INTO ids VALUES (10); +INSERT INTO ids VALUES (3); +INSERT INTO ids VALUES (9); + +CREATE INDEX grnindex ON ids USING pgroonga (id); + +SET enable_seqscan = off; +SET enable_indexscan = on; + +SELECT id + FROM ids + ORDER BY id ASC + LIMIT 5; + +DROP TABLE ids; Modified: test.sql (+4 -4) =================================================================== --- test.sql 2015-02-06 00:06:30 +0900 (5038978) +++ test.sql 2015-02-06 00:17:31 +0900 (985c8ff) @@ -4,19 +4,19 @@ CREATE TABLE memos ( title text ); -INSERT INTO memos VALUES (1, 'PostgreSQL'); INSERT INTO memos VALUES (2, 'Groonga'); INSERT INTO memos VALUES (3, 'PGroonga'); +INSERT INTO memos VALUES (1, 'PostgreSQL'); -CREATE INDEX grnindex ON memos USING pgroonga (title pgroonga.text_ops); +CREATE INDEX grnindex ON memos USING pgroonga (id); SET enable_seqscan = off; SET enable_indexscan = on; -SET enable_bitmapscan = off; +SET enable_bitmapscan = on; SELECT id, title FROM memos - WHERE title = 'Groonga'; + ORDER BY id DESC LIMIT 2; DROP TABLE memos; -------------- next part -------------- HTML����������������������������...Download