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