From: shess Date: Thu, 13 Sep 2007 18:14:49 +0000 (+0000) Subject: Add an implicit (HIDDEN) docid column. This works as an alias to X-Git-Tag: version-3.6.10~1751 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d83ae45639e2ac8d9cacd52443bc66b2993317af;p=thirdparty%2Fsqlite.git Add an implicit (HIDDEN) docid column. This works as an alias to rowid, similar to how things work in SQLite tables with INTEGER PRIMARY KEY. Add tests to verify operation. (CVS 4426) FossilOrigin-Name: c8d2345200f9ece1af712543982097d0b6f348c7 --- diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index af3a557945..605e7c5d27 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -2702,7 +2702,10 @@ static char *fulltextSchema( zSchema = zNext; zSep = ","; } - zNext = sqlite3_mprintf("%s,%Q HIDDEN)", zSchema, zTableName); + zNext = sqlite3_mprintf("%s,%Q HIDDEN", zSchema, zTableName); + sqlite3_free(zSchema); + zSchema = zNext; + zNext = sqlite3_mprintf("%s,docid HIDDEN)", zSchema); sqlite3_free(zSchema); return zNext; } @@ -2861,6 +2864,7 @@ out: /* Decide how to handle an SQL query. */ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ + fulltext_vtab *v = (fulltext_vtab *)pVTab; int i; TRACE(("FTS3 BestIndex\n")); @@ -2868,11 +2872,11 @@ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ const struct sqlite3_index_constraint *pConstraint; pConstraint = &pInfo->aConstraint[i]; if( pConstraint->usable ) { - if( pConstraint->iColumn==-1 && + if( (pConstraint->iColumn==-1 || pConstraint->iColumn==v->nColumn+1) && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ pInfo->idxNum = QUERY_DOCID; /* lookup by docid */ TRACE(("FTS3 QUERY_DOCID\n")); - } else if( pConstraint->iColumn>=0 && + } else if( pConstraint->iColumn>=0 && pConstraint->iColumn<=v->nColumn && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ /* full-text search */ pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn; @@ -3763,6 +3767,10 @@ static int fulltextColumn(sqlite3_vtab_cursor *pCursor, ** Return a blob which is a pointer to the cursor */ sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); + }else if( idxCol==v->nColumn+1 ){ + /* The docid column, which is an alias for rowid. */ + sqlite3_value *pVal = sqlite3_column_value(c->pStmt, 0); + sqlite3_result_value(pContext, pVal); } return SQLITE_OK; } @@ -5674,13 +5682,17 @@ static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, * ppArg[1] = new rowid * ppArg[2..2+v->nColumn-1] = values * ppArg[2+v->nColumn] = value for magic column (we ignore this) + * ppArg[2+v->nColumn+1] = value for docid */ sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]); if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER || - sqlite3_value_int64(ppArg[1]) != rowid ){ + sqlite3_value_int64(ppArg[1]) != rowid ){ rc = SQLITE_ERROR; /* we don't allow changing the rowid */ - } else { - assert( nArg==2+v->nColumn+1); + }else if( sqlite3_value_type(ppArg[2+v->nColumn+1]) != SQLITE_INTEGER || + sqlite3_value_int64(ppArg[2+v->nColumn+1]) != rowid ){ + rc = SQLITE_ERROR; /* we don't allow changing the docid */ + }else{ + assert( nArg==2+v->nColumn+2); rc = index_update(v, rowid, &ppArg[2]); } } else { @@ -5688,9 +5700,26 @@ static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, * ppArg[1] = requested rowid * ppArg[2..2+v->nColumn-1] = values * ppArg[2+v->nColumn] = value for magic column (we ignore this) + * ppArg[2+v->nColumn+1] = value for docid */ - assert( nArg==2+v->nColumn+1); - rc = index_insert(v, ppArg[1], &ppArg[2], pRowid); + sqlite3_value *pRequestDocid = ppArg[2+v->nColumn+1]; + assert( nArg==2+v->nColumn+2); + if( SQLITE_NULL != sqlite3_value_type(pRequestDocid) && + SQLITE_NULL != sqlite3_value_type(ppArg[1]) ){ + /* TODO(shess) Consider allowing this to work if the values are + ** identical. I'm inclined to discourage that usage, though, + ** given that both rowid and docid are special columns. Better + ** would be to define one or the other as the default winner, + ** but should it be fts3-centric (docid) or SQLite-centric + ** (rowid)? + */ + rc = SQLITE_ERROR; + }else{ + if( SQLITE_NULL == sqlite3_value_type(pRequestDocid) ){ + pRequestDocid = ppArg[1]; + } + rc = index_insert(v, pRequestDocid, &ppArg[2], pRowid); + } } return rc; diff --git a/manifest b/manifest index 9d7f544bd4..e5b461d656 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Mark\sthe\stable-named\scolumn\sHIDDEN.\s\sAdd\stests\sto\smake\ssure\sit's\nworking\sas\sexpected.\s(CVS\s4425) -D 2007-09-13T18:12:10 +C Add\san\simplicit\s(HIDDEN)\sdocid\scolumn.\s\sThis\sworks\sas\san\salias\sto\nrowid,\ssimilar\sto\show\sthings\swork\sin\sSQLite\stables\swith\sINTEGER\nPRIMARY\sKEY.\s\sAdd\stests\sto\sverify\soperation.\s(CVS\s4426) +D 2007-09-13T18:14:49 F Makefile.in cbfb898945536a8f9ea8b897e1586dd1fdbcc5db F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -49,7 +49,7 @@ F ext/fts2/fts2_tokenizer1.c 8a545c232bdffafd117c4eeaf59789691909f26a F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0 F ext/fts3/README.tokenizers a97c9a55b3422f6cb04af9de9296fe2447ea4a78 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c fa62f3981802f260bd2131f7aabb532e7957b537 +F ext/fts3/fts3.c 6d266d7250a544ae27026dc5caf655b94f63d74b F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3_hash.c 84654768178452b00bbc986dd878a8299dc1e3dc F ext/fts3/fts3_hash.h af585d6867d478fc0457f64cfaae60e09541e63a @@ -304,7 +304,7 @@ F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8 F test/fts3an.test 2da4df52fe8ea8389f6fa7a01e4c1a0f091118d6 F test/fts3ao.test 0aa29dd4fc1c8d46b1f7cfe5926f7ac97551bea9 F test/fts3atoken.test 25c2070e1e8755d414bf9c8200427b277a9f99fa -F test/fts3b.test 7c697946fe11b651c4531c522519f8c50bc333ec +F test/fts3b.test b3a25180a633873d37d86e1ccd00ed690d37237a F test/func.test 590fe3e1d28256d98dd73efb671de0823043e82a F test/fuzz.test 62fc19dd36a427777fd671b569df07166548628a F test/fuzz2.test ea38692ce2da99ad79fe0be5eb1a452c1c4d37bb @@ -577,7 +577,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 2cfdbfe6543bac42961deecec7d085d806e604b5 -R f4605f4a6437f7ace832bd72a3a46cf2 +P ca669eaf1b4af441741129bee4af02f32a7c74b8 +R a51a9cf24cdebc5c4ac36a19e3d14834 U shess -Z 8703f97ca6b737d36a523e680d867934 +Z 890136427fcf1284643fc3a90d814552 diff --git a/manifest.uuid b/manifest.uuid index 476aaced21..a57a8d5389 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ca669eaf1b4af441741129bee4af02f32a7c74b8 \ No newline at end of file +c8d2345200f9ece1af712543982097d0b6f348c7 \ No newline at end of file diff --git a/test/fts3b.test b/test/fts3b.test index 770e97cd9d..17ee0da85a 100644 --- a/test/fts3b.test +++ b/test/fts3b.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. This # script tests for the fts2 rowid-versus-vacuum problem (ticket #2566). # -# $Id: fts3b.test,v 1.2 2007/09/13 18:12:10 shess Exp $ +# $Id: fts3b.test,v 1.3 2007/09/13 18:14:49 shess Exp $ # set testdir [file dirname $argv0] @@ -136,4 +136,83 @@ do_test fts3b-3.3 { } } {} +# fts3 adds a new implicit column, docid, which acts as an alias for +# rowid. + +db eval { + CREATE VIRTUAL TABLE t4 USING fts3(c); + INSERT INTO t4 (c) VALUES('this is a test'); + INSERT INTO t4 (c) VALUES('that was a test'); + INSERT INTO t4 (c) VALUES('this is fun'); + DELETE FROM t4 WHERE c = 'that was a test'; +} + +# Test that docid is present and identical to rowid. +do_test fts3b-4.1 { + execsql { + SELECT rowid FROM t4 WHERE rowid <> docid; + } +} {} + +# Test that docid is hidden. +do_test fts3b-4.2 { + execsql { + SELECT * FROM t4 WHERE rowid = 1; + } +} {{this is a test}} + +# Test that docid can be selected. +do_test fts3b-4.3 { + execsql { + SELECT docid, * FROM t4 WHERE rowid = 1; + } +} {1 {this is a test}} + +# Test that docid can be used in WHERE. +do_test fts3b-4.4 { + execsql { + SELECT docid, * FROM t4 WHERE docid = 1; + } +} {1 {this is a test}} + +# Test that the column doesn't conflict with inserts that don't name +# columns. [Yes, this is the same as fts3b-3.3, here just in case the +# goals of that test change.] +do_test fts3b-4.5 { + execsql { + INSERT INTO t4 VALUES ('another test'); + } +} {} + +# Test that the docid can be forced on insert. +do_test fts3b-4.6 { + execsql { + INSERT INTO t4 (docid, c) VALUES (10, 'yet another test'); + SELECT * FROM t4 WHERE docid = 10; + } +} {{yet another test}} + +# Test that rowid can also be forced. +do_test fts3b-4.7 { + execsql { + INSERT INTO t4 (docid, c) VALUES (12, 'still testing'); + SELECT * FROM t4 WHERE docid = 12; + } +} {{still testing}} + +# If an insert tries to set both docid and rowid, require an error. +do_test fts3b-4.8 { + catchsql { + INSERT INTO t4 (rowid, docid, c) VALUES (14, 15, 'bad test'); + SELECT * FROM t4 WHERE docid = 14; + } +} {1 {SQL logic error or missing database}} + +# Don't allow update of docid, to match rowid behaviour. +do_test fts3b-4.9 { + catchsql { + UPDATE t4 SET docid = 14 WHERE docid = 12; + } +} {1 {SQL logic error or missing database}} + finish_test